Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
Actor Framework
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
cpp-libs
Actor Framework
Commits
309795fb
Commit
309795fb
authored
Nov 03, 2015
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add new traverse API for network devices
parent
3b131411
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
103 additions
and
124 deletions
+103
-124
libcaf_io/caf/io/network/interfaces.hpp
libcaf_io/caf/io/network/interfaces.hpp
+16
-1
libcaf_io/src/interfaces.cpp
libcaf_io/src/interfaces.cpp
+87
-123
No files found.
libcaf_io/caf/io/network/interfaces.hpp
View file @
309795fb
...
@@ -24,6 +24,7 @@
...
@@ -24,6 +24,7 @@
#include <vector>
#include <vector>
#include <string>
#include <string>
#include <utility>
#include <utility>
#include <initializer_list>
#include "caf/optional.hpp"
#include "caf/optional.hpp"
...
@@ -42,18 +43,32 @@ using interfaces_map = std::map<std::string, address_listing>;
...
@@ -42,18 +43,32 @@ using interfaces_map = std::map<std::string, address_listing>;
/// Utility class bundling access to network interface names and addresses.
/// Utility class bundling access to network interface names and addresses.
class
interfaces
{
class
interfaces
{
public:
public:
/// Consumes `{interface_name, protocol_type, is_localhost, address}` entries.
using
consumer
=
std
::
function
<
void
(
const
char
*
,
protocol
,
bool
,
const
char
*
)
>
;
/// Traverses all network interfaces for given protocols using `f`.
static
void
traverse
(
std
::
initializer_list
<
protocol
>
ps
,
consumer
f
);
/// Traverses all network interfaces using `f`.
static
void
traverse
(
consumer
f
);
/// Returns a map listing each interface by its name.
/// Returns a map listing each interface by its name.
static
interfaces_map
list_all
(
bool
include_localhost
=
true
);
static
interfaces_map
list_all
(
bool
include_localhost
=
true
);
/// Returns all addresses for all devices for all protocols.
/// Returns all addresses for all devices for all protocols.
static
address_listing
list_addresses
(
bool
include_localhost
=
true
);
static
address_listing
list_addresses
(
bool
include_localhost
=
true
);
/// Returns all addresses for all devices for given protocols.
static
std
::
vector
<
std
::
string
>
list_addresses
(
std
::
initializer_list
<
protocol
>
procs
,
bool
include_localhost
=
true
);
/// Returns all addresses for all devices for given protocol.
/// Returns all addresses for all devices for given protocol.
static
std
::
vector
<
std
::
string
>
list_addresses
(
protocol
proc
,
static
std
::
vector
<
std
::
string
>
list_addresses
(
protocol
proc
,
bool
include_localhost
=
true
);
bool
include_localhost
=
true
);
/// Returns a native IPv4 or IPv6 translation of `host`.
/// Returns a native IPv4 or IPv6 translation of `host`.
///*/
static
optional
<
std
::
pair
<
std
::
string
,
protocol
>>
static
optional
<
std
::
pair
<
std
::
string
,
protocol
>>
native_address
(
const
std
::
string
&
host
,
optional
<
protocol
>
preferred
=
none
);
native_address
(
const
std
::
string
&
host
,
optional
<
protocol
>
preferred
=
none
);
};
};
...
...
libcaf_io/src/interfaces.cpp
View file @
309795fb
...
@@ -57,63 +57,46 @@ using interfaces_map = std::map<std::string,
...
@@ -57,63 +57,46 @@ using interfaces_map = std::map<std::string,
std
::
map
<
protocol
,
std
::
map
<
protocol
,
std
::
vector
<
std
::
string
>>>
;
std
::
vector
<
std
::
string
>>>
;
in6_addr
*
fetch_in_addr
(
sockaddr_in6
*
addr
)
{
template
<
class
T
>
return
&
(
addr
->
sin6_addr
);
void
*
vptr
(
T
*
ptr
)
{
return
static_cast
<
void
*>
(
ptr
);
}
}
in_addr
*
fetch_in_addr
(
sockaddr_in
*
addr
)
{
void
*
fetch_in_addr
(
int
family
,
sockaddr
*
addr
)
{
return
&
(
addr
->
sin_addr
);
if
(
family
==
AF_INET
)
return
vptr
(
&
reinterpret_cast
<
sockaddr_in
*>
(
addr
)
->
sin_addr
);
return
vptr
(
&
reinterpret_cast
<
sockaddr_in6
*>
(
addr
)
->
sin6_addr
);
}
}
template
<
int
Family
,
class
SockAddr
>
int
fetch_addr_str
(
bool
get_ipv4
,
bool
get_ipv6
,
void
add_addr_as_string
(
std
::
vector
<
std
::
string
>&
res
,
SockAddr
*
addr
)
{
char
(
&
buf
)[
INET6_ADDRSTRLEN
],
auto
in_addr
=
fetch_in_addr
(
addr
);
sockaddr
*
addr
)
{
char
address_buffer
[
INET6_ADDRSTRLEN
+
1
];
if
(
!
addr
)
inet_ntop
(
Family
,
in_addr
,
address_buffer
,
INET6_ADDRSTRLEN
);
return
AF_UNSPEC
;
res
.
push_back
(
address_buffer
);
auto
family
=
addr
->
sa_family
;
auto
in_addr
=
fetch_in_addr
(
family
,
addr
);
return
((
family
==
AF_INET
&&
get_ipv4
)
||
(
family
==
AF_INET6
&&
get_ipv6
))
&&
inet_ntop
(
family
,
in_addr
,
buf
,
INET6_ADDRSTRLEN
)
==
buf
?
family
:
AF_UNSPEC
;
}
}
#ifdef CAF_WINDOWS
#ifdef CAF_WINDOWS
using
if_device_ptr
=
IP_ADAPTER_ADDRESSES
*
;
// F consumes `{interface_name, protocol, is_localhost, address}` entries.
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
>
template
<
class
F
>
void
for_each_
device
(
bool
include_localhost
,
F
fun
)
{
void
for_each_
address
(
bool
get_ipv4
,
bool
get_ipv6
,
F
fun
)
{
ULONG
tmp_size
=
16
*
1024
;
// try 16kb buffer first
ULONG
tmp_size
=
16
*
1024
;
// try 16kb buffer first
IP_ADAPTER_ADDRESSES
*
tmp
=
nullptr
;
IP_ADAPTER_ADDRESSES
*
tmp
=
nullptr
;
constexpr
size_t
max_tries
=
3
;
constexpr
size_t
max_tries
=
3
;
size_t
try_nr
=
0
;
size_t
try_nr
=
0
;
int
retval
=
0
;
int
retval
=
0
;
do
{
do
{
if
(
tmp
!=
nullptr
)
{
if
(
tmp
!=
nullptr
)
free
(
tmp
);
free
(
tmp
);
}
tmp
=
reinterpret_cast
<
IP_ADAPTER_ADDRESSES
*>
(
malloc
(
tmp_size
));
tmp
=
reinterpret_cast
<
IP_ADAPTER_ADDRESSES
*>
(
malloc
(
tmp_size
));
if
(
tmp
==
nullptr
)
{
if
(
tmp
==
nullptr
)
throw
std
::
bad_alloc
();
throw
std
::
bad_alloc
();
}
retval
=
GetAdaptersAddresses
(
AF_UNSPEC
,
GAA_FLAG_INCLUDE_PREFIX
,
retval
=
GetAdaptersAddresses
(
AF_UNSPEC
,
GAA_FLAG_INCLUDE_PREFIX
,
nullptr
,
tmp
,
&
tmp_size
);
nullptr
,
tmp
,
&
tmp_size
);
}
while
(
retval
==
ERROR_BUFFER_OVERFLOW
&&
++
try_nr
<
max_tries
);
}
while
(
retval
==
ERROR_BUFFER_OVERFLOW
&&
++
try_nr
<
max_tries
);
...
@@ -138,67 +121,69 @@ void for_each_device(bool include_localhost, F fun) {
...
@@ -138,67 +121,69 @@ void for_each_device(bool include_localhost, F fun) {
}
}
return
;
return
;
}
}
char
buffer
[
INET6_ADDRSTRLEN
];
for
(
auto
i
=
ifs
.
get
();
i
!=
nullptr
;
i
=
i
->
Next
)
{
for
(
auto
i
=
ifs
.
get
();
i
!=
nullptr
;
i
=
i
->
Next
)
{
fun
(
i
);
for
(
auto
j
=
i
->
FirstUnicastAddress
;
j
!=
nullptr
;
j
=
j
->
Next
)
{
auto
addr
=
j
->
Address
.
lpSockaddr
;
auto
family
=
fetch_addr_str
(
get_ipv4
,
get_ipv6
,
buffer
,
addr
);
if
(
family
!=
AF_UNSPEC
)
fun
(
i
->
AdapterName
,
family
==
AF_INET
?
protocol
::
ipv4
:
protocol
::
ipv6
,
false
,
buffer
);
}
}
}
}
}
#else // ifdef CAF_WINDOWS
#else // ifdef CAF_WINDOWS
// interface address pointer
// F consumes `{interface_name, protocol, is_localhost, address}` entries.
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_
address
(
bool
get_ipv4
,
bool
get_ipv6
,
F
fun
)
{
if
_device_ptr
tmp
=
nullptr
;
if
addrs
*
tmp
=
nullptr
;
if
(
getifaddrs
(
&
tmp
)
!=
0
)
{
if
(
getifaddrs
(
&
tmp
)
!=
0
)
{
perror
(
"getifaddrs"
);
perror
(
"getifaddrs"
);
return
;
return
;
}
}
char
buffer
[
INET6_ADDRSTRLEN
];
std
::
unique_ptr
<
ifaddrs
,
decltype
(
freeifaddrs
)
*>
ifs
{
tmp
,
freeifaddrs
};
std
::
unique_ptr
<
ifaddrs
,
decltype
(
freeifaddrs
)
*>
ifs
{
tmp
,
freeifaddrs
};
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
=
fetch_addr_str
(
get_ipv4
,
get_ipv6
,
buffer
,
i
->
ifa_addr
);
if
(
include_localhost
)
{
if
(
family
!=
AF_UNSPEC
)
fun
(
i
);
fun
(
i
->
ifa_name
,
family
==
AF_INET
?
protocol
::
ipv4
:
protocol
::
ipv6
,
}
else
if
(
family
==
AF_INET
||
family
==
AF_INET6
)
{
(
i
->
ifa_flags
&
IFF_LOOPBACK
)
!=
0
,
// filter loopback devices
buffer
);
if
((
i
->
ifa_flags
&
IFF_LOOPBACK
)
==
0
)
{
fun
(
i
);
}
}
}
}
}
}
#endif // ifdef CAF_WINDOWS
#endif // ifdef CAF_WINDOWS
namespace
{
template
<
class
F
>
void
traverse_impl
(
std
::
initializer_list
<
protocol
>
ps
,
F
f
)
{
if
(
std
::
find
(
ps
.
begin
(),
ps
.
end
(),
protocol
::
ethernet
)
!=
ps
.
end
())
for
(
auto
&
pair
:
detail
::
get_mac_addresses
())
f
(
pair
.
first
.
c_str
(),
protocol
::
ethernet
,
false
,
pair
.
second
.
c_str
());
auto
get_ipv4
=
std
::
find
(
ps
.
begin
(),
ps
.
end
(),
protocol
::
ipv4
)
!=
ps
.
end
();
auto
get_ipv6
=
std
::
find
(
ps
.
begin
(),
ps
.
end
(),
protocol
::
ipv6
)
!=
ps
.
end
();
for_each_address
(
get_ipv4
,
get_ipv6
,
f
);
}
}
// namespace <anonymous>
void
interfaces
::
traverse
(
std
::
initializer_list
<
protocol
>
ps
,
consumer
f
)
{
traverse_impl
(
ps
,
f
);
}
void
interfaces
::
traverse
(
consumer
f
)
{
traverse_impl
({
protocol
::
ethernet
,
protocol
::
ipv4
,
protocol
::
ipv6
},
f
);
}
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
())
{
traverse_impl
({
protocol
::
ethernet
,
protocol
::
ipv4
,
protocol
::
ipv6
},
result
[
pair
.
first
][
protocol
::
ethernet
].
push_back
(
std
::
move
(
pair
.
second
));
[
&
](
const
char
*
name
,
protocol
p
,
bool
lo
,
const
char
*
addr
)
{
}
if
(
include_localhost
||
!
lo
)
for_each_device
(
include_localhost
,
[
&
](
if_device_ptr
i
)
{
result
[
name
][
p
].
push_back
(
addr
);
add_addr
<
AF_INET
>
(
i
,
result
[
if_device_name
(
i
)][
protocol
::
ipv4
]);
add_addr
<
AF_INET6
>
(
i
,
result
[
if_device_name
(
i
)][
protocol
::
ipv6
]);
});
});
return
result
;
return
result
;
}
}
...
@@ -206,68 +191,47 @@ interfaces_map interfaces::list_all(bool include_localhost) {
...
@@ -206,68 +191,47 @@ interfaces_map interfaces::list_all(bool include_localhost) {
std
::
map
<
protocol
,
std
::
vector
<
std
::
string
>>
std
::
map
<
protocol
,
std
::
vector
<
std
::
string
>>
interfaces
::
list_addresses
(
bool
include_localhost
)
{
interfaces
::
list_addresses
(
bool
include_localhost
)
{
std
::
map
<
protocol
,
std
::
vector
<
std
::
string
>>
result
;
std
::
map
<
protocol
,
std
::
vector
<
std
::
string
>>
result
;
for
(
auto
&
pair
:
detail
::
get_mac_addresses
())
{
traverse_impl
({
protocol
::
ethernet
,
protocol
::
ipv4
,
protocol
::
ipv6
},
result
[
protocol
::
ethernet
].
push_back
(
std
::
move
(
pair
.
second
));
[
&
](
const
char
*
,
protocol
p
,
bool
lo
,
const
char
*
addr
)
{
}
if
(
include_localhost
||
!
lo
)
for_each_device
(
include_localhost
,
[
&
](
if_device_ptr
i
)
{
result
[
p
].
push_back
(
addr
);
add_addr
<
AF_INET
>
(
i
,
result
[
protocol
::
ipv4
]);
add_addr
<
AF_INET6
>
(
i
,
result
[
protocol
::
ipv6
]);
});
});
return
result
;
return
result
;
}
}
std
::
vector
<
std
::
string
>
interfaces
::
list_addresses
(
protocol
proc
,
std
::
vector
<
std
::
string
>
bool
include_localhost
)
{
interfaces
::
list_addresses
(
std
::
initializer_list
<
protocol
>
procs
,
bool
include_localhost
)
{
std
::
vector
<
std
::
string
>
result
;
std
::
vector
<
std
::
string
>
result
;
switch
(
proc
)
{
traverse_impl
(
procs
,
[
&
](
const
char
*
,
protocol
,
bool
lo
,
const
char
*
addr
)
{
case
protocol
:
:
ethernet
:
if
(
include_localhost
||
!
lo
)
for
(
auto
&
pair
:
detail
::
get_mac_addresses
())
{
result
.
push_back
(
addr
);
result
.
push_back
(
std
::
move
(
pair
.
second
));
});
}
break
;
case
protocol
:
:
ipv4
:
for_each_device
(
include_localhost
,
[
&
](
if_device_ptr
i
)
{
add_addr
<
AF_INET
>
(
i
,
result
);
});
break
;
case
protocol
:
:
ipv6
:
for_each_device
(
include_localhost
,
[
&
](
if_device_ptr
i
)
{
add_addr
<
AF_INET6
>
(
i
,
result
);
});
break
;
}
return
result
;
return
result
;
}
}
std
::
vector
<
std
::
string
>
interfaces
::
list_addresses
(
protocol
proc
,
bool
include_localhost
)
{
return
list_addresses
({
proc
},
include_localhost
);
}
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
)
{
addrinfo
hint
;
addrinfo
hint
;
memset
(
&
hint
,
0
,
sizeof
(
hint
));
memset
(
&
hint
,
0
,
sizeof
(
hint
));
hint
.
ai_socktype
=
SOCK_STREAM
;
hint
.
ai_socktype
=
SOCK_STREAM
;
if
(
preferred
)
{
if
(
preferred
)
hint
.
ai_family
=
*
preferred
==
protocol
::
ipv4
?
AF_INET
:
AF_INET6
;
hint
.
ai_family
=
*
preferred
==
protocol
::
ipv4
?
AF_INET
:
AF_INET6
;
}
addrinfo
*
tmp
=
nullptr
;
addrinfo
*
tmp
=
nullptr
;
if
(
getaddrinfo
(
host
.
c_str
(),
nullptr
,
&
hint
,
&
tmp
))
{
if
(
getaddrinfo
(
host
.
c_str
(),
nullptr
,
&
hint
,
&
tmp
))
return
none
;
return
none
;
}
std
::
unique_ptr
<
addrinfo
,
decltype
(
freeaddrinfo
)
*>
addrs
{
tmp
,
freeaddrinfo
};
std
::
unique_ptr
<
addrinfo
,
decltype
(
freeaddrinfo
)
*>
addrs
{
tmp
,
freeaddrinfo
};
char
buffer
[
INET6_ADDRSTRLEN
];
for
(
auto
i
=
addrs
.
get
();
i
!=
nullptr
;
i
=
i
->
ai_next
)
{
for
(
auto
i
=
addrs
.
get
();
i
!=
nullptr
;
i
=
i
->
ai_next
)
{
auto
family
=
i
->
ai_family
;
auto
family
=
fetch_addr_str
(
true
,
true
,
buffer
,
i
->
ai_addr
);
if
(
family
==
AF_INET
||
family
==
AF_INET6
)
{
if
(
family
!=
AF_UNSPEC
)
char
buffer
[
INET6_ADDRSTRLEN
];
return
{{
buffer
,
family
==
AF_INET
?
protocol
::
ipv4
:
protocol
::
ipv6
}};
auto
res
=
family
==
AF_INET
?
inet_ntop
(
family
,
&
reinterpret_cast
<
sockaddr_in
*>
(
i
->
ai_addr
)
->
sin_addr
,
buffer
,
sizeof
(
buffer
))
:
inet_ntop
(
family
,
&
reinterpret_cast
<
sockaddr_in6
*>
(
i
->
ai_addr
)
->
sin6_addr
,
buffer
,
sizeof
(
buffer
));
if
(
res
!=
nullptr
)
{
return
{{
res
,
family
==
AF_INET
?
protocol
::
ipv4
:
protocol
::
ipv6
}};
}
}
}
}
return
none
;
return
none
;
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment