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
c1d3b4db
Commit
c1d3b4db
authored
Sep 29, 2017
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Distinct between network and transport protocol
parent
85483265
Changes
9
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
138 additions
and
73 deletions
+138
-73
libcaf_io/CMakeLists.txt
libcaf_io/CMakeLists.txt
+7
-6
libcaf_io/caf/io/network/default_multiplexer.hpp
libcaf_io/caf/io/network/default_multiplexer.hpp
+3
-3
libcaf_io/caf/io/network/interfaces.hpp
libcaf_io/caf/io/network/interfaces.hpp
+10
-9
libcaf_io/caf/io/network/protocol.hpp
libcaf_io/caf/io/network/protocol.hpp
+35
-9
libcaf_io/src/basp_broker.cpp
libcaf_io/src/basp_broker.cpp
+1
-3
libcaf_io/src/default_multiplexer.cpp
libcaf_io/src/default_multiplexer.cpp
+3
-3
libcaf_io/src/interfaces.cpp
libcaf_io/src/interfaces.cpp
+31
-30
libcaf_io/src/protocol.cpp
libcaf_io/src/protocol.cpp
+37
-0
tools/caf-run.cpp
tools/caf-run.cpp
+11
-10
No files found.
libcaf_io/CMakeLists.txt
View file @
c1d3b4db
...
@@ -7,22 +7,23 @@ file(GLOB_RECURSE LIBCAF_IO_HDRS "caf/*.hpp")
...
@@ -7,22 +7,23 @@ file(GLOB_RECURSE LIBCAF_IO_HDRS "caf/*.hpp")
# list cpp files excluding platform-dependent files
# list cpp files excluding platform-dependent files
set
(
LIBCAF_IO_SRCS
set
(
LIBCAF_IO_SRCS
src/basp_broker.cpp
src/abstract_broker.cpp
src/abstract_broker.cpp
src/acceptor_manager.cpp
src/basp_broker.cpp
src/broker.cpp
src/broker.cpp
src/default_multiplexer.cpp
src/default_multiplexer.cpp
src/doorman.cpp
src/doorman.cpp
src/middleman.cpp
src/middleman_actor.cpp
src/middleman_actor_impl.cpp
src/hook.cpp
src/hook.cpp
src/interfaces.cpp
src/interfaces.cpp
src/manager.cpp
src/manager.cpp
src/middleman.cpp
src/middleman_actor.cpp
src/middleman_actor_impl.cpp
src/multiplexer.cpp
src/protocol.cpp
src/scribe.cpp
src/scribe.cpp
src/stream_manager.cpp
src/stream_manager.cpp
src/test_multiplexer.cpp
src/test_multiplexer.cpp
src/acceptor_manager.cpp
src/multiplexer.cpp
# BASP files
# BASP files
src/header.cpp
src/header.cpp
src/message_type.cpp
src/message_type.cpp
...
...
libcaf_io/caf/io/network/default_multiplexer.hpp
View file @
c1d3b4db
...
@@ -676,9 +676,9 @@ private:
...
@@ -676,9 +676,9 @@ private:
ProtocolPolicy
policy_
;
ProtocolPolicy
policy_
;
};
};
expected
<
native_socket
>
new_tcp_connection
(
const
std
::
string
&
host
,
expected
<
native_socket
>
uint16_t
port
,
new_tcp_connection
(
const
std
::
string
&
host
,
uint16_t
port
,
optional
<
protocol
>
preferred
=
none
);
optional
<
protocol
::
network
>
preferred
=
none
);
expected
<
native_socket
>
new_tcp_acceptor_impl
(
uint16_t
port
,
const
char
*
addr
,
expected
<
native_socket
>
new_tcp_acceptor_impl
(
uint16_t
port
,
const
char
*
addr
,
bool
reuse_addr
);
bool
reuse_addr
);
...
...
libcaf_io/caf/io/network/interfaces.hpp
View file @
c1d3b4db
...
@@ -36,7 +36,7 @@ namespace io {
...
@@ -36,7 +36,7 @@ namespace io {
namespace
network
{
namespace
network
{
// {protocol => address}
// {protocol => address}
using
address_listing
=
std
::
map
<
protocol
,
std
::
vector
<
std
::
string
>>
;
using
address_listing
=
std
::
map
<
protocol
::
network
,
std
::
vector
<
std
::
string
>>
;
// {interface_name => {protocol => address}}
// {interface_name => {protocol => address}}
using
interfaces_map
=
std
::
map
<
std
::
string
,
address_listing
>
;
using
interfaces_map
=
std
::
map
<
std
::
string
,
address_listing
>
;
...
@@ -45,11 +45,11 @@ using interfaces_map = std::map<std::string, address_listing>;
...
@@ -45,11 +45,11 @@ using interfaces_map = std::map<std::string, address_listing>;
class
interfaces
{
class
interfaces
{
public:
public:
/// Consumes `{interface_name, protocol_type, is_localhost, address}` entries.
/// Consumes `{interface_name, protocol_type, is_localhost, address}` entries.
using
consumer
=
std
::
function
<
void
(
const
char
*
,
protocol
,
using
consumer
=
std
::
function
<
void
(
const
char
*
,
protocol
::
network
,
bool
,
const
char
*
)
>
;
bool
,
const
char
*
)
>
;
/// Traverses all network interfaces for given protocols using `f`.
/// Traverses all network interfaces for given protocols using `f`.
static
void
traverse
(
std
::
initializer_list
<
protocol
>
ps
,
consumer
f
);
static
void
traverse
(
std
::
initializer_list
<
protocol
::
network
>
ps
,
consumer
f
);
/// Traverses all network interfaces using `f`.
/// Traverses all network interfaces using `f`.
static
void
traverse
(
consumer
f
);
static
void
traverse
(
consumer
f
);
...
@@ -62,21 +62,22 @@ public:
...
@@ -62,21 +62,22 @@ public:
/// Returns all addresses for all devices for given protocols.
/// Returns all addresses for all devices for given protocols.
static
std
::
vector
<
std
::
string
>
static
std
::
vector
<
std
::
string
>
list_addresses
(
std
::
initializer_list
<
protocol
>
procs
,
list_addresses
(
std
::
initializer_list
<
protocol
::
network
>
procs
,
bool
include_localhost
=
true
);
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
::
network
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
::
network
>>
native_address
(
const
std
::
string
&
host
,
optional
<
protocol
>
preferred
=
none
);
native_address
(
const
std
::
string
&
host
,
optional
<
protocol
::
network
>
preferred
=
none
);
/// Returns the host and protocol available for a local server socket
/// Returns the host and protocol available for a local server socket
static
std
::
vector
<
std
::
pair
<
std
::
string
,
protocol
>>
static
std
::
vector
<
std
::
pair
<
std
::
string
,
protocol
::
network
>>
server_address
(
uint16_t
port
,
const
char
*
host
,
server_address
(
uint16_t
port
,
const
char
*
host
,
optional
<
protocol
>
preferred
=
none
);
optional
<
protocol
::
network
>
preferred
=
none
);
};
};
}
// namespace network
}
// namespace network
...
...
libcaf_io/caf/io/network/protocol.hpp
View file @
c1d3b4db
...
@@ -21,25 +21,51 @@
...
@@ -21,25 +21,51 @@
#define CAF_IO_NETWORK_PROTOCOL_HPP
#define CAF_IO_NETWORK_PROTOCOL_HPP
#include <cstddef>
#include <cstddef>
#include <string>
#include "caf/meta/type_name.hpp"
namespace
caf
{
namespace
caf
{
namespace
io
{
namespace
io
{
namespace
network
{
namespace
network
{
/// Denotes a network protocol, e.g., Ethernet or IP4/6.
/// Bundles protocol information for network and transport layer communication.
enum
class
protocol
:
uint32_t
{
struct
protocol
{
ethernet
,
/// Denotes a network protocol, i.e., IPv4 or IPv6.
enum
network
{
ipv4
,
ipv4
,
ipv6
ipv6
};
/// Denotes a transport protocol, i.e., TCP or UDP.
enum
transport
{
tcp
,
udp
};
transport
trans
;
network
net
;
};
};
/// @relates protocol::transport
inline
std
::
string
to_string
(
protocol
::
transport
x
)
{
return
x
==
protocol
::
tcp
?
"TCP"
:
"UDP"
;
}
/// @relates protocol::network
inline
std
::
string
to_string
(
protocol
::
network
x
)
{
return
x
==
protocol
::
ipv4
?
"IPv4"
:
"IPv6"
;
}
/// @relates protocol
/// @relates protocol
inline
std
::
string
to_string
(
protocol
value
)
{
template
<
class
Inspector
>
return
value
==
protocol
::
ethernet
?
"ethernet"
typename
Inspector
::
result_type
inspect
(
Inspector
&
f
,
protocol
&
x
)
{
:
(
value
==
protocol
::
ipv4
?
"ipv4"
return
f
(
meta
::
type_name
(
"protocol"
),
x
.
trans
,
x
.
net
);
:
"ipv6"
);
}
}
/// Converts a protocol into a transport/network string representation, e.g.,
/// "TCP/IPv4".
/// @relates protocol
std
::
string
to_string
(
const
protocol
&
x
);
}
// namespace network
}
// namespace network
}
// namespace io
}
// namespace io
}
// namespace caf
}
// namespace caf
...
...
libcaf_io/src/basp_broker.cpp
View file @
c1d3b4db
...
@@ -401,7 +401,6 @@ void basp_broker_state::learned_new_node_indirectly(const node_id& nid) {
...
@@ -401,7 +401,6 @@ void basp_broker_state::learned_new_node_indirectly(const node_id& nid) {
[
&
](
uint16_t
port
,
network
::
address_listing
&
addresses
)
{
[
&
](
uint16_t
port
,
network
::
address_listing
&
addresses
)
{
auto
&
mx
=
system
().
middleman
().
backend
();
auto
&
mx
=
system
().
middleman
().
backend
();
for
(
auto
&
kvp
:
addresses
)
for
(
auto
&
kvp
:
addresses
)
if
(
kvp
.
first
!=
network
::
protocol
::
ethernet
)
for
(
auto
&
addr
:
kvp
.
second
)
{
for
(
auto
&
addr
:
kvp
.
second
)
{
auto
hdl
=
mx
.
new_tcp_scribe
(
addr
,
port
);
auto
hdl
=
mx
.
new_tcp_scribe
(
addr
,
port
);
if
(
hdl
)
{
if
(
hdl
)
{
...
@@ -411,7 +410,6 @@ void basp_broker_state::learned_new_node_indirectly(const node_id& nid) {
...
@@ -411,7 +410,6 @@ void basp_broker_state::learned_new_node_indirectly(const node_id& nid) {
helper
->
send
(
s
,
connect_atom
::
value
,
*
hdl
,
port
);
helper
->
send
(
s
,
connect_atom
::
value
,
*
hdl
,
port
);
return
;
return
;
}
}
// else: simply try next address
}
}
CAF_LOG_INFO
(
"could not connect to node directly:"
<<
CAF_ARG
(
nid
));
CAF_LOG_INFO
(
"could not connect to node directly:"
<<
CAF_ARG
(
nid
));
}
}
...
...
libcaf_io/src/default_multiplexer.cpp
View file @
c1d3b4db
...
@@ -1153,9 +1153,9 @@ bool ip_connect(native_socket fd, const std::string& host, uint16_t port) {
...
@@ -1153,9 +1153,9 @@ bool ip_connect(native_socket fd, const std::string& host, uint16_t port) {
return
connect
(
fd
,
reinterpret_cast
<
const
sockaddr
*>
(
&
sa
),
sizeof
(
sa
))
==
0
;
return
connect
(
fd
,
reinterpret_cast
<
const
sockaddr
*>
(
&
sa
),
sizeof
(
sa
))
==
0
;
}
}
expected
<
native_socket
>
new_tcp_connection
(
const
std
::
string
&
host
,
expected
<
native_socket
>
uint16_t
port
,
new_tcp_connection
(
const
std
::
string
&
host
,
uint16_t
port
,
optional
<
protocol
>
preferred
)
{
optional
<
protocol
::
network
>
preferred
)
{
CAF_LOG_TRACE
(
CAF_ARG
(
host
)
<<
CAF_ARG
(
port
)
<<
CAF_ARG
(
preferred
));
CAF_LOG_TRACE
(
CAF_ARG
(
host
)
<<
CAF_ARG
(
port
)
<<
CAF_ARG
(
preferred
));
CAF_LOG_INFO
(
"try to connect to:"
<<
CAF_ARG
(
host
)
<<
CAF_ARG
(
port
));
CAF_LOG_INFO
(
"try to connect to:"
<<
CAF_ARG
(
host
)
<<
CAF_ARG
(
port
));
auto
res
=
interfaces
::
native_address
(
host
,
std
::
move
(
preferred
));
auto
res
=
interfaces
::
native_address
(
host
,
std
::
move
(
preferred
));
...
...
libcaf_io/src/interfaces.cpp
View file @
c1d3b4db
...
@@ -56,7 +56,7 @@ namespace network {
...
@@ -56,7 +56,7 @@ namespace network {
// {interface_name => {protocol => address}}
// {interface_name => {protocol => address}}
using
interfaces_map
=
std
::
map
<
std
::
string
,
using
interfaces_map
=
std
::
map
<
std
::
string
,
std
::
map
<
protocol
,
std
::
map
<
protocol
::
network
,
std
::
vector
<
std
::
string
>>>
;
std
::
vector
<
std
::
string
>>>
;
template
<
class
T
>
template
<
class
T
>
...
@@ -161,10 +161,7 @@ void for_each_address(bool get_ipv4, bool get_ipv6, F fun) {
...
@@ -161,10 +161,7 @@ void for_each_address(bool get_ipv4, bool get_ipv6, F fun) {
namespace
{
namespace
{
template
<
class
F
>
template
<
class
F
>
void
traverse_impl
(
std
::
initializer_list
<
protocol
>
ps
,
F
f
)
{
void
traverse_impl
(
std
::
initializer_list
<
protocol
::
network
>
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_ipv4
=
std
::
find
(
ps
.
begin
(),
ps
.
end
(),
protocol
::
ipv4
)
!=
ps
.
end
();
auto
get_ipv6
=
std
::
find
(
ps
.
begin
(),
ps
.
end
(),
protocol
::
ipv6
)
!=
ps
.
end
();
auto
get_ipv6
=
std
::
find
(
ps
.
begin
(),
ps
.
end
(),
protocol
::
ipv6
)
!=
ps
.
end
();
for_each_address
(
get_ipv4
,
get_ipv6
,
f
);
for_each_address
(
get_ipv4
,
get_ipv6
,
f
);
...
@@ -172,29 +169,32 @@ void traverse_impl(std::initializer_list<protocol> ps, F f) {
...
@@ -172,29 +169,32 @@ void traverse_impl(std::initializer_list<protocol> ps, F f) {
}
// namespace <anonymous>
}
// namespace <anonymous>
void
interfaces
::
traverse
(
std
::
initializer_list
<
protocol
>
ps
,
consumer
f
)
{
void
interfaces
::
traverse
(
std
::
initializer_list
<
protocol
::
network
>
ps
,
consumer
f
)
{
traverse_impl
(
ps
,
std
::
move
(
f
));
traverse_impl
(
ps
,
std
::
move
(
f
));
}
}
void
interfaces
::
traverse
(
consumer
f
)
{
void
interfaces
::
traverse
(
consumer
f
)
{
traverse_impl
({
protocol
::
ethernet
,
protocol
::
ipv4
,
protocol
::
ipv6
},
std
::
move
(
f
));
traverse_impl
({
protocol
::
ipv4
,
protocol
::
ipv6
},
std
::
move
(
f
));
}
}
interfaces_map
interfaces
::
list_all
(
bool
include_localhost
)
{
interfaces_map
interfaces
::
list_all
(
bool
include_localhost
)
{
interfaces_map
result
;
interfaces_map
result
;
traverse_impl
({
protocol
::
ethernet
,
protocol
::
ipv4
,
protocol
::
ipv6
},
traverse_impl
(
[
&
](
const
char
*
name
,
protocol
p
,
bool
lo
,
const
char
*
addr
)
{
{
protocol
::
ipv4
,
protocol
::
ipv6
},
[
&
](
const
char
*
name
,
protocol
::
network
p
,
bool
lo
,
const
char
*
addr
)
{
if
(
include_localhost
||
!
lo
)
if
(
include_localhost
||
!
lo
)
result
[
name
][
p
].
emplace_back
(
addr
);
result
[
name
][
p
].
emplace_back
(
addr
);
});
});
return
result
;
return
result
;
}
}
std
::
map
<
protocol
,
std
::
vector
<
std
::
string
>>
std
::
map
<
protocol
::
network
,
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
::
network
,
std
::
vector
<
std
::
string
>>
result
;
traverse_impl
({
protocol
::
ethernet
,
protocol
::
ipv4
,
protocol
::
ipv6
},
traverse_impl
(
[
&
](
const
char
*
,
protocol
p
,
bool
lo
,
const
char
*
addr
)
{
{
protocol
::
ipv4
,
protocol
::
ipv6
},
[
&
](
const
char
*
,
protocol
::
network
p
,
bool
lo
,
const
char
*
addr
)
{
if
(
include_localhost
||
!
lo
)
if
(
include_localhost
||
!
lo
)
result
[
p
].
emplace_back
(
addr
);
result
[
p
].
emplace_back
(
addr
);
});
});
...
@@ -202,24 +202,25 @@ interfaces::list_addresses(bool include_localhost) {
...
@@ -202,24 +202,25 @@ interfaces::list_addresses(bool include_localhost) {
}
}
std
::
vector
<
std
::
string
>
std
::
vector
<
std
::
string
>
interfaces
::
list_addresses
(
std
::
initializer_list
<
protocol
>
procs
,
interfaces
::
list_addresses
(
std
::
initializer_list
<
protocol
::
network
>
procs
,
bool
include_localhost
)
{
bool
include_localhost
)
{
std
::
vector
<
std
::
string
>
result
;
std
::
vector
<
std
::
string
>
result
;
traverse_impl
(
procs
,
[
&
](
const
char
*
,
protocol
,
bool
lo
,
const
char
*
addr
)
{
traverse_impl
(
procs
,
[
&
](
const
char
*
,
protocol
::
network
,
bool
lo
,
const
char
*
addr
)
{
if
(
include_localhost
||
!
lo
)
if
(
include_localhost
||
!
lo
)
result
.
emplace_back
(
addr
);
result
.
emplace_back
(
addr
);
});
});
return
result
;
return
result
;
}
}
std
::
vector
<
std
::
string
>
interfaces
::
list_addresses
(
protocol
proc
,
std
::
vector
<
std
::
string
>
interfaces
::
list_addresses
(
protocol
::
network
proc
,
bool
include_localhost
)
{
bool
include_localhost
)
{
return
list_addresses
({
proc
},
include_localhost
);
return
list_addresses
({
proc
},
include_localhost
);
}
}
optional
<
std
::
pair
<
std
::
string
,
protocol
>>
optional
<
std
::
pair
<
std
::
string
,
protocol
::
network
>>
interfaces
::
native_address
(
const
std
::
string
&
host
,
interfaces
::
native_address
(
const
std
::
string
&
host
,
optional
<
protocol
>
preferred
)
{
optional
<
protocol
::
network
>
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
;
...
@@ -239,10 +240,10 @@ interfaces::native_address(const std::string& host,
...
@@ -239,10 +240,10 @@ interfaces::native_address(const std::string& host,
return
none
;
return
none
;
}
}
std
::
vector
<
std
::
pair
<
std
::
string
,
protocol
>>
std
::
vector
<
std
::
pair
<
std
::
string
,
protocol
::
network
>>
interfaces
::
server_address
(
uint16_t
port
,
const
char
*
host
,
interfaces
::
server_address
(
uint16_t
port
,
const
char
*
host
,
optional
<
protocol
>
preferred
)
{
optional
<
protocol
::
network
>
preferred
)
{
using
addr_pair
=
std
::
pair
<
std
::
string
,
protocol
>
;
using
addr_pair
=
std
::
pair
<
std
::
string
,
protocol
::
network
>
;
addrinfo
hint
;
addrinfo
hint
;
memset
(
&
hint
,
0
,
sizeof
(
hint
));
memset
(
&
hint
,
0
,
sizeof
(
hint
));
hint
.
ai_socktype
=
SOCK_STREAM
;
hint
.
ai_socktype
=
SOCK_STREAM
;
...
...
libcaf_io/src/protocol.cpp
0 → 100644
View file @
c1d3b4db
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2017 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include "caf/io/network/protocol.hpp"
namespace
caf
{
namespace
io
{
namespace
network
{
std
::
string
to_string
(
const
protocol
&
x
)
{
std
::
string
result
;
result
+=
to_string
(
x
.
trans
);
result
+=
"/"
;
result
+=
to_string
(
x
.
net
);
return
result
;
}
}
// namespace network
}
// namespace io
}
// namespace caf
tools/caf-run.cpp
View file @
c1d3b4db
...
@@ -201,8 +201,9 @@ void bootstrap(actor_system& system,
...
@@ -201,8 +201,9 @@ void bootstrap(actor_system& system,
<<
" --caf#slave-name="
<<
slave
.
host
<<
" --caf#slave-name="
<<
slave
.
host
<<
" --caf#bootstrap-node="
;
<<
" --caf#bootstrap-node="
;
bool
is_first
=
true
;
bool
is_first
=
true
;
interfaces
::
traverse
({
protocol
::
ipv4
,
protocol
::
ipv6
},
interfaces
::
traverse
(
[
&
](
const
char
*
,
protocol
,
bool
lo
,
const
char
*
x
)
{
{
protocol
::
ipv4
,
protocol
::
ipv6
},
[
&
](
const
char
*
,
protocol
::
network
,
bool
lo
,
const
char
*
x
)
{
if
(
lo
)
if
(
lo
)
return
;
return
;
if
(
!
is_first
)
if
(
!
is_first
)
...
...
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