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
7bedcd63
Commit
7bedcd63
authored
Jan 29, 2019
by
Joseph Noir
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Rework automatic connections to new nodes
parent
adc4041d
Changes
11
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
597 additions
and
639 deletions
+597
-639
libcaf_io/caf/io/basp/instance.hpp
libcaf_io/caf/io/basp/instance.hpp
+16
-12
libcaf_io/caf/io/basp/routing_table.hpp
libcaf_io/caf/io/basp/routing_table.hpp
+49
-43
libcaf_io/caf/io/basp_broker.hpp
libcaf_io/caf/io/basp_broker.hpp
+11
-5
libcaf_io/caf/io/connection_helper.hpp
libcaf_io/caf/io/connection_helper.hpp
+1
-6
libcaf_io/src/basp_broker.cpp
libcaf_io/src/basp_broker.cpp
+118
-67
libcaf_io/src/connection_helper.cpp
libcaf_io/src/connection_helper.cpp
+19
-71
libcaf_io/src/instance.cpp
libcaf_io/src/instance.cpp
+46
-35
libcaf_io/src/middleman.cpp
libcaf_io/src/middleman.cpp
+2
-1
libcaf_io/src/routing_table.cpp
libcaf_io/src/routing_table.cpp
+61
-97
libcaf_io/test/automatic_connection.cpp
libcaf_io/test/automatic_connection.cpp
+267
-198
libcaf_io/test/basp.cpp
libcaf_io/test/basp.cpp
+7
-104
No files found.
libcaf_io/caf/io/basp/instance.hpp
View file @
7bedcd63
...
@@ -80,14 +80,8 @@ public:
...
@@ -80,14 +80,8 @@ public:
std
::
vector
<
strong_actor_ptr
>&
forwarding_stack
,
std
::
vector
<
strong_actor_ptr
>&
forwarding_stack
,
message
&
msg
)
=
0
;
message
&
msg
)
=
0
;
/// Called whenever BASP learns the ID of a remote node
/// Called whenever BASP learns the ID of a remote node.
/// to which it does not have a direct connection.
virtual
void
learned_new_node
(
const
node_id
&
nid
)
=
0
;
virtual
void
learned_new_node_directly
(
const
node_id
&
nid
,
bool
was_known_indirectly
)
=
0
;
/// Called whenever BASP learns the ID of a remote node
/// to which it does not have a direct connection.
virtual
void
learned_new_node_indirectly
(
const
node_id
&
nid
)
=
0
;
/// Called if a heartbeat was received from `nid`
/// Called if a heartbeat was received from `nid`
virtual
void
handle_heartbeat
(
const
node_id
&
nid
)
=
0
;
virtual
void
handle_heartbeat
(
const
node_id
&
nid
)
=
0
;
...
@@ -107,9 +101,19 @@ public:
...
@@ -107,9 +101,19 @@ public:
return
namespace_
.
system
().
config
();
return
namespace_
.
system
().
config
();
}
}
/// Send messages that were buffered while connectivity establishment
/// was pending using `hdl`.
virtual
void
send_buffered_messages
(
execution_unit
*
ctx
,
node_id
nid
,
connection_handle
hdl
)
=
0
;
/// Returns a reference to the sent buffer.
/// Returns a reference to the sent buffer.
virtual
buffer_type
&
get_buffer
(
connection_handle
hdl
)
=
0
;
virtual
buffer_type
&
get_buffer
(
connection_handle
hdl
)
=
0
;
/// Returns a reference to a buffer to be sent to node with `nid`.
/// If communication with the node is esstablished, it picks the first
/// available handle, otherwise a buffer for a pending message is returned.
virtual
buffer_type
&
get_buffer
(
node_id
nid
)
=
0
;
/// Flushes the underlying write buffer of `hdl`.
/// Flushes the underlying write buffer of `hdl`.
virtual
void
flush
(
connection_handle
hdl
)
=
0
;
virtual
void
flush
(
connection_handle
hdl
)
=
0
;
...
@@ -135,15 +139,15 @@ public:
...
@@ -135,15 +139,15 @@ public:
void
handle_heartbeat
(
execution_unit
*
ctx
);
void
handle_heartbeat
(
execution_unit
*
ctx
);
/// Returns a route to `target` or `none` on error.
/// Returns a route to `target` or `none` on error.
optional
<
routing_table
::
route
>
lookup
(
const
node_id
&
target
);
routing_table
::
lookup_result
lookup
(
const
node_id
&
target
);
/// Flushes the underlying buffer of `path`.
/// Flushes the underlying buffer of `path`.
void
flush
(
con
st
routing_table
::
route
&
path
);
void
flush
(
con
nection_handle
hdl
);
/// Sends a BASP message and implicitly flushes the output buffer of `r`.
/// Sends a BASP message and implicitly flushes the output buffer of `r`.
/// This function will update `hdr.payload_len` if a payload was written.
/// This function will update `hdr.payload_len` if a payload was written.
void
write
(
execution_unit
*
ctx
,
con
st
routing_table
::
route
&
r
,
void
write
(
execution_unit
*
ctx
,
con
nection_handle
hdl
,
header
&
hd
r
,
header
&
hdr
,
payload_writer
*
writer
=
nullptr
);
payload_writer
*
writer
=
nullptr
);
/// Adds a new actor to the map of published actors.
/// Adds a new actor to the map of published actors.
void
add_published_actor
(
uint16_t
port
,
void
add_published_actor
(
uint16_t
port
,
...
...
libcaf_io/caf/io/basp/routing_table.hpp
View file @
7bedcd63
...
@@ -43,64 +43,69 @@ public:
...
@@ -43,64 +43,69 @@ public:
virtual
~
routing_table
();
virtual
~
routing_table
();
/// Describes a routing path to a node.
/// Result for a lookup of a node.
struct
route
{
struct
lookup_result
{
const
node_id
&
next_hop
;
/// Tracks whether the node is already known.
connection_handle
hdl
;
bool
known
;
/// Servant handle to communicate with the node -- if already created.
optional
<
connection_handle
>
hdl
;
};
};
/// Describes a function object for erase operations that
/// Describes a function object for erase operations that
/// is called for each indirectly lost connection.
/// is called for each indirectly lost connection.
using
erase_callback
=
callback
<
const
node_id
&>
;
using
erase_callback
=
callback
<
const
node_id
&>
;
/// Returns a route to `target` or `none` on error.
/// Returns the ID of the peer reachable via `hdl` or
optional
<
route
>
lookup
(
const
node_id
&
target
);
/// Returns the ID of the peer connected via `hdl` or
/// `none` if `hdl` is unknown.
/// `none` if `hdl` is unknown.
node_id
lookup_direct
(
const
connection_handle
&
hdl
)
const
;
node_id
lookup
(
const
connection_handle
&
hdl
)
const
;
/// Returns the handle offering a direct connection to `nid` or
/// `invalid_connection_handle` if no direct connection to `nid` exists.
optional
<
connection_handle
>
lookup_direct
(
const
node_id
&
nid
)
const
;
/// Returns the
next hop that would be chosen for `nid`
/// Returns the
state for communication with `nid` along with a handle
///
or `none` if there's no indirect route to `nid`
.
///
if communication is established or `none` if `nid` is unknown
.
node_id
lookup_indirect
(
const
node_id
&
nid
)
const
;
lookup_result
lookup
(
const
node_id
&
nid
)
const
;
/// Adds a new
direct route
to the table.
/// Adds a new
endpoint
to the table.
/// @pre `hdl != invalid_connection_handle && nid != none`
/// @pre `hdl != invalid_connection_handle && nid != none`
void
add
_direct
(
const
connection_handle
&
hdl
,
const
node_id
&
nid
);
void
add
(
const
node_id
&
nid
,
const
connection_handle
&
hdl
);
/// Adds a new indirect route to the table.
/// Add a new endpoint to the table.
bool
add_indirect
(
const
node_id
&
hop
,
const
node_id
&
dest
);
/// @pre `origin != none && nid != none`
void
add
(
const
node_id
&
nid
,
const
node_id
&
origin
);
/// Blacklist the route to `dest` via `hop`.
/// Adds a new endpoint to the table that has no attached information.
void
blacklist
(
const
node_id
&
hop
,
const
node_id
&
dest
);
/// that propagated information about the node.
/// @pre `nid != none`
void
add
(
const
node_id
&
nid
);
/// Removes a direct connection and calls `cb` for any node
/// Removes a direct connection and calls `cb` for any node
/// that became unreachable as a result of this operation,
/// that became unreachable as a result of this operation,
/// including the node that is assigned as direct path for `hdl`.
/// including the node that is assigned as direct path for `hdl`.
void
erase
_direct
(
const
connection_handle
&
hdl
,
erase_callback
&
cb
);
void
erase
(
const
connection_handle
&
hdl
,
erase_callback
&
cb
);
/// Removes any entry for indirect connection to `dest` and returns
/// Queries whether `dest` is reachable directly.
/// `true` if `dest` had an indirect route, otherwise `false`.
bool
erase_indirect
(
const
node_id
&
dest
);
/// Queries whether `dest` is reachable.
bool
reachable
(
const
node_id
&
dest
);
bool
reachable
(
const
node_id
&
dest
);
/// Removes all direct and indirect routes to `dest` and calls
/// `cb` for any node that became unreachable as a result of this
/// operation, including `dest`.
/// @returns the number of removed routes (direct and indirect)
size_t
erase
(
const
node_id
&
dest
,
erase_callback
&
cb
);
/// Returns the parent broker.
/// Returns the parent broker.
inline
abstract_broker
*
parent
()
{
inline
abstract_broker
*
parent
()
{
return
parent_
;
return
parent_
;
}
}
/// Set the forwarding node that first mentioned `hdl`.
bool
origin
(
const
node_id
&
nid
,
const
node_id
&
origin
);
/// Get the forwarding node that first mentioned `hdl`
/// or `none` if the node is unknown.
optional
<
node_id
>
origin
(
const
node_id
&
nid
);
/// Set the handle for communication with `nid`.
bool
handle
(
const
node_id
&
nid
,
const
connection_handle
&
hdl
);
/// Get the handle for communication with `nid`
/// or `none` if the node is unknown.
optional
<
connection_handle
>
handle
(
const
node_id
&
nid
);
/// Get the addresses to reach `nid` or `none` if the node is unknown.
optional
<
const
endpoint
&>
address
(
const
node_id
&
nid
);
/// Returns the local autoconnect endpoint.
/// Returns the local autoconnect endpoint.
const
endpoint
&
autoconnect_endpoint
();
const
endpoint
&
autoconnect_endpoint
();
...
@@ -108,6 +113,14 @@ public:
...
@@ -108,6 +113,14 @@ public:
void
autoconnect_endpoint
(
uint16_t
,
network
::
address_listing
);
void
autoconnect_endpoint
(
uint16_t
,
network
::
address_listing
);
public:
public:
/// Entry to bundle information for a remote endpoint.
struct
node_info
{
/// Handle for the node if communication is established.
optional
<
connection_handle
>
hdl
;
/// The endpoint who told us about the node.
optional
<
node_id
>
origin
;
};
template
<
class
Map
,
class
Fallback
>
template
<
class
Map
,
class
Fallback
>
typename
Map
::
mapped_type
typename
Map
::
mapped_type
get_opt
(
const
Map
&
m
,
const
typename
Map
::
key_type
&
k
,
Fallback
&&
x
)
const
{
get_opt
(
const
Map
&
m
,
const
typename
Map
::
key_type
&
k
,
Fallback
&&
x
)
const
{
...
@@ -117,16 +130,9 @@ public:
...
@@ -117,16 +130,9 @@ public:
return
std
::
forward
<
Fallback
>
(
x
);
return
std
::
forward
<
Fallback
>
(
x
);
}
}
using
node_id_set
=
std
::
unordered_set
<
node_id
>
;
using
indirect_entries
=
std
::
unordered_map
<
node_id
,
// dest
node_id_set
>
;
// hop
abstract_broker
*
parent_
;
abstract_broker
*
parent_
;
std
::
unordered_map
<
connection_handle
,
node_id
>
direct_by_hdl_
;
std
::
unordered_map
<
connection_handle
,
node_id
>
nid_by_hdl_
;
std
::
unordered_map
<
node_id
,
connection_handle
>
direct_by_nid_
;
std
::
unordered_map
<
node_id
,
node_info
>
node_information_base_
;
indirect_entries
indirect_
;
indirect_entries
blacklist_
;
endpoint
autoconnect_endpoint_
;
endpoint
autoconnect_endpoint_
;
};
};
...
...
libcaf_io/caf/io/basp_broker.hpp
View file @
7bedcd63
...
@@ -77,17 +77,17 @@ struct basp_broker_state : proxy_registry::backend, basp::instance::callee {
...
@@ -77,17 +77,17 @@ struct basp_broker_state : proxy_registry::backend, basp::instance::callee {
std
::
vector
<
strong_actor_ptr
>&
stages
,
message
&
msg
);
std
::
vector
<
strong_actor_ptr
>&
stages
,
message
&
msg
);
// performs bookkeeping such as managing `spawn_servers`
// performs bookkeeping such as managing `spawn_servers`
void
learned_new_node
(
const
node_id
&
nid
);
void
learned_new_node
(
const
node_id
&
nid
)
override
;
// inherited from basp::instance::callee
// inherited from basp::instance::callee
void
learned_new_node_directly
(
const
node_id
&
nid
,
void
send_buffered_messages
(
execution_unit
*
ctx
,
node_id
nid
,
bool
was_indirectly_before
)
override
;
connection_handle
hdl
)
override
;
// inherited from basp::instance::callee
// inherited from basp::instance::callee
void
learned_new_node_indirectly
(
const
node_id
&
nid
)
override
;
buffer_type
&
get_buffer
(
connection_handle
hdl
)
override
;
// inherited from basp::instance::callee
// inherited from basp::instance::callee
buffer_type
&
get_buffer
(
connection_handle
hdl
)
override
;
buffer_type
&
get_buffer
(
node_id
nid
)
override
;
// inherited from basp::instance::callee
// inherited from basp::instance::callee
void
flush
(
connection_handle
hdl
)
override
;
void
flush
(
connection_handle
hdl
)
override
;
...
@@ -102,6 +102,9 @@ struct basp_broker_state : proxy_registry::backend, basp::instance::callee {
...
@@ -102,6 +102,9 @@ struct basp_broker_state : proxy_registry::backend, basp::instance::callee {
/// Cleans up any state for `hdl`.
/// Cleans up any state for `hdl`.
void
cleanup
(
connection_handle
hdl
);
void
cleanup
(
connection_handle
hdl
);
/// Try to establish a connection to node with `nid`.
void
connect
(
const
node_id
&
nid
);
// pointer to ourselves
// pointer to ourselves
broker
*
self
;
broker
*
self
;
...
@@ -146,6 +149,9 @@ struct basp_broker_state : proxy_registry::backend, basp::instance::callee {
...
@@ -146,6 +149,9 @@ struct basp_broker_state : proxy_registry::backend, basp::instance::callee {
// actor
// actor
void
handle_down_msg
(
down_msg
&
);
void
handle_down_msg
(
down_msg
&
);
// buffer messages for nodes while connectivity is established
std
::
unordered_map
<
node_id
,
std
::
vector
<
buffer_type
>>
pending_connectivity
;
static
const
char
*
name
;
static
const
char
*
name
;
};
};
...
...
libcaf_io/caf/io/connection_helper.hpp
View file @
7bedcd63
...
@@ -46,13 +46,8 @@ struct connection_helper_state {
...
@@ -46,13 +46,8 @@ struct connection_helper_state {
static
const
char
*
name
;
static
const
char
*
name
;
};
};
behavior
datagram_connection_broker
(
broker
*
self
,
uint16_t
port
,
network
::
address_listing
addresses
,
actor
system_broker
);
behavior
connection_helper
(
stateful_actor
<
connection_helper_state
>*
self
,
behavior
connection_helper
(
stateful_actor
<
connection_helper_state
>*
self
,
actor
b
);
actor
system_broker
);
}
// namespace io
}
// namespace io
}
// namespace caf
}
// namespace caf
libcaf_io/src/basp_broker.cpp
View file @
7bedcd63
This diff is collapsed.
Click to expand it.
libcaf_io/src/connection_helper.cpp
View file @
7bedcd63
...
@@ -34,97 +34,45 @@ auto autoconnect_timeout = std::chrono::minutes(10);
...
@@ -34,97 +34,45 @@ auto autoconnect_timeout = std::chrono::minutes(10);
const
char
*
connection_helper_state
::
name
=
"connection_helper"
;
const
char
*
connection_helper_state
::
name
=
"connection_helper"
;
behavior
datagram_connection_broker
(
broker
*
self
,
uint16_t
port
,
network
::
address_listing
addresses
,
actor
system_broker
)
{
auto
&
mx
=
self
->
system
().
middleman
().
backend
();
auto
&
this_node
=
self
->
system
().
node
();
auto
app_id
=
get_or
(
self
->
config
(),
"middleman.app-identifier"
,
defaults
::
middleman
::
app_identifier
);
for
(
auto
&
kvp
:
addresses
)
{
for
(
auto
&
addr
:
kvp
.
second
)
{
auto
eptr
=
mx
.
new_remote_udp_endpoint
(
addr
,
port
);
if
(
eptr
)
{
auto
hdl
=
(
*
eptr
)
->
hdl
();
self
->
add_datagram_servant
(
std
::
move
(
*
eptr
));
// TODO: UDP does not work at the moment.
// basp::instance::write_client_handshake(self->context(),
// self->wr_buf(hdl), this_node,
// app_id);
static_cast
<
void
>
(
this_node
);
static_cast
<
void
>
(
hdl
);
}
}
}
return
{
[
=
](
new_datagram_msg
&
msg
)
{
auto
hdl
=
msg
.
handle
;
self
->
send
(
system_broker
,
std
::
move
(
msg
),
self
->
take
(
hdl
),
port
);
self
->
quit
();
},
after
(
autoconnect_timeout
)
>>
[
=
]()
{
CAF_LOG_TRACE
(
CAF_ARG
(
""
));
// nothing heard in about 10 minutes... just a call it a day, then
CAF_LOG_INFO
(
"aborted direct connection attempt after 10min"
);
self
->
quit
(
exit_reason
::
user_shutdown
);
}
};
}
behavior
connection_helper
(
stateful_actor
<
connection_helper_state
>*
self
,
behavior
connection_helper
(
stateful_actor
<
connection_helper_state
>*
self
,
actor
b
)
{
actor
system_broker
)
{
CAF_LOG_TRACE
(
CAF_ARG
(
b
));
CAF_LOG_TRACE
(
CAF_ARG
(
system_broker
));
self
->
monitor
(
b
);
self
->
monitor
(
system_broker
);
self
->
set_down_handler
([
=
](
down_msg
&
dm
)
{
self
->
set_down_handler
([
=
](
down_msg
&
dm
)
{
CAF_LOG_TRACE
(
CAF_ARG
(
dm
));
CAF_LOG_TRACE
(
CAF_ARG
(
dm
));
self
->
quit
(
std
::
move
(
dm
.
reason
));
self
->
quit
(
std
::
move
(
dm
.
reason
));
});
});
return
{
return
{
// this config is send from the remote `
Config
Serv`
// this config is send from the remote `
Peer
Serv`
[
=
](
const
std
::
string
&
item
,
message
&
msg
)
{
[
=
](
const
std
::
string
&
item
,
message
&
msg
)
{
CAF_LOG_TRACE
(
CAF_ARG
(
item
)
<<
CAF_ARG
(
msg
));
CAF_LOG_TRACE
(
CAF_ARG
(
item
)
<<
CAF_ARG
(
msg
));
CAF_LOG_DEBUG
(
"received requested
config
:"
<<
CAF_ARG
(
msg
));
CAF_LOG_DEBUG
(
"received requested
address
:"
<<
CAF_ARG
(
msg
));
// whatever happens, we are done afterwards
// whatever happens, we are done afterwards
self
->
quit
();
self
->
quit
();
msg
.
apply
({
msg
.
apply
({
[
&
](
uint16_t
port
,
network
::
address_listing
&
addresses
)
{
[
&
](
basp
::
routing_table
::
endpoint
&
ep
)
{
if
(
item
==
"basp.default-connectivity-tcp"
)
{
auto
port
=
ep
.
first
;
auto
&
mx
=
self
->
system
().
middleman
().
backend
();
auto
&
addrs
=
ep
.
second
;
for
(
auto
&
kvp
:
addresses
)
{
auto
&
mx
=
self
->
system
().
middleman
().
backend
();
for
(
auto
&
addr
:
kvp
.
second
)
{
for
(
auto
&
kvp
:
addrs
)
{
auto
hdl
=
mx
.
new_tcp_scribe
(
addr
,
port
);
for
(
auto
&
addr
:
kvp
.
second
)
{
if
(
hdl
)
{
auto
hdl
=
mx
.
new_tcp_scribe
(
addr
,
port
);
// gotcha! send scribe to our BASP broker
if
(
hdl
)
{
// to initiate handshake etc.
// Gotcha! Send scribe to our broker to initiate handshake etc.
CAF_LOG_INFO
(
"connected directly:"
<<
CAF_ARG
(
addr
));
CAF_LOG_INFO
(
"connected directly:"
<<
CAF_ARG
(
addr
));
self
->
send
(
b
,
connect_atom
::
value
,
*
hdl
,
port
);
self
->
send
(
system_broker
,
connect_atom
::
value
,
*
hdl
,
port
);
return
;
return
;
}
}
}
}
}
CAF_LOG_INFO
(
"could not connect to node directly"
);
}
else
if
(
item
==
"basp.default-connectivity-udp"
)
{
auto
&
sys
=
self
->
system
();
// create new broker to try addresses for communication via UDP
if
(
get_or
(
sys
.
config
(),
"middleman.attach-utility-actors"
,
false
))
self
->
system
().
middleman
().
spawn_broker
<
hidden
>
(
datagram_connection_broker
,
port
,
std
::
move
(
addresses
),
b
);
else
self
->
system
().
middleman
().
spawn_broker
<
detached
+
hidden
>
(
datagram_connection_broker
,
port
,
std
::
move
(
addresses
),
b
);
}
else
{
CAF_LOG_INFO
(
"aborted direct connection attempt, unknown item: "
<<
CAF_ARG
(
item
));
}
}
CAF_LOG_ERROR
(
"could not connect to node "
);
}
}
});
});
},
},
after
(
autoconnect_timeout
)
>>
[
=
]
{
after
(
autoconnect_timeout
)
>>
[
=
]
{
CAF_LOG_TRACE
(
CAF_ARG
(
""
));
CAF_LOG_TRACE
(
CAF_ARG
(
""
));
// nothing heard in about 10 minutes... just a call it a day, then
// nothing heard in about 10 minutes... just a call it a day, then
CAF_LOG_INFO
(
"aborted
direct
connection attempt after 10min"
);
CAF_LOG_INFO
(
"aborted connection attempt after 10min"
);
self
->
quit
(
exit_reason
::
user_shutdown
);
self
->
quit
(
exit_reason
::
user_shutdown
);
}
}
};
};
...
...
libcaf_io/src/instance.cpp
View file @
7bedcd63
...
@@ -55,7 +55,7 @@ connection_state instance::handle(execution_unit* ctx,
...
@@ -55,7 +55,7 @@ connection_state instance::handle(execution_unit* ctx,
callee_
.
purge_state
(
nid
);
callee_
.
purge_state
(
nid
);
return
none
;
return
none
;
});
});
tbl_
.
erase
_direct
(
dm
.
handle
,
cb
);
tbl_
.
erase
(
dm
.
handle
,
cb
);
return
close_connection
;
return
close_connection
;
};
};
std
::
vector
<
char
>*
payload
=
nullptr
;
std
::
vector
<
char
>*
payload
=
nullptr
;
...
@@ -86,27 +86,27 @@ connection_state instance::handle(execution_unit* ctx,
...
@@ -86,27 +86,27 @@ connection_state instance::handle(execution_unit* ctx,
void
instance
::
handle_heartbeat
(
execution_unit
*
ctx
)
{
void
instance
::
handle_heartbeat
(
execution_unit
*
ctx
)
{
CAF_LOG_TRACE
(
""
);
CAF_LOG_TRACE
(
""
);
for
(
auto
&
kvp
:
tbl_
.
direct
_by_hdl_
)
{
for
(
auto
&
kvp
:
tbl_
.
nid
_by_hdl_
)
{
CAF_LOG_TRACE
(
CAF_ARG
(
kvp
.
first
)
<<
CAF_ARG
(
kvp
.
second
));
CAF_LOG_TRACE
(
CAF_ARG
(
kvp
.
first
)
<<
CAF_ARG
(
kvp
.
second
));
write_heartbeat
(
ctx
,
callee_
.
get_buffer
(
kvp
.
first
));
write_heartbeat
(
ctx
,
callee_
.
get_buffer
(
kvp
.
first
));
callee_
.
flush
(
kvp
.
first
);
callee_
.
flush
(
kvp
.
first
);
}
}
}
}
optional
<
routing_table
::
route
>
instance
::
lookup
(
const
node_id
&
target
)
{
routing_table
::
lookup_result
instance
::
lookup
(
const
node_id
&
target
)
{
return
tbl_
.
lookup
(
target
);
return
tbl_
.
lookup
(
target
);
}
}
void
instance
::
flush
(
con
st
routing_table
::
route
&
path
)
{
void
instance
::
flush
(
con
nection_handle
hdl
)
{
callee_
.
flush
(
path
.
hdl
);
callee_
.
flush
(
hdl
);
}
}
void
instance
::
write
(
execution_unit
*
ctx
,
con
st
routing_table
::
route
&
r
,
void
instance
::
write
(
execution_unit
*
ctx
,
con
nection_handle
hdl
,
header
&
hdr
,
payload_writer
*
writer
)
{
header
&
hdr
,
payload_writer
*
writer
)
{
CAF_LOG_TRACE
(
CAF_ARG
(
hdr
));
CAF_LOG_TRACE
(
CAF_ARG
(
hdr
));
CAF_ASSERT
(
hdr
.
payload_len
==
0
||
writer
!=
nullptr
);
CAF_ASSERT
(
hdr
.
payload_len
==
0
||
writer
!=
nullptr
);
write
(
ctx
,
callee_
.
get_buffer
(
r
.
hdl
),
hdr
,
writer
);
write
(
ctx
,
callee_
.
get_buffer
(
hdl
),
hdr
,
writer
);
flush
(
r
);
flush
(
hdl
);
}
}
void
instance
::
add_published_actor
(
uint16_t
port
,
void
instance
::
add_published_actor
(
uint16_t
port
,
...
@@ -169,8 +169,8 @@ bool instance::dispatch(execution_unit* ctx, const strong_actor_ptr& sender,
...
@@ -169,8 +169,8 @@ bool instance::dispatch(execution_unit* ctx, const strong_actor_ptr& sender,
CAF_LOG_TRACE
(
CAF_ARG
(
sender
)
<<
CAF_ARG
(
receiver
)
CAF_LOG_TRACE
(
CAF_ARG
(
sender
)
<<
CAF_ARG
(
receiver
)
<<
CAF_ARG
(
mid
)
<<
CAF_ARG
(
msg
));
<<
CAF_ARG
(
mid
)
<<
CAF_ARG
(
msg
));
CAF_ASSERT
(
receiver
&&
system
().
node
()
!=
receiver
->
node
());
CAF_ASSERT
(
receiver
&&
system
().
node
()
!=
receiver
->
node
());
auto
path
=
lookup
(
receiver
->
node
());
auto
lr
=
lookup
(
receiver
->
node
());
if
(
!
path
)
{
if
(
!
lr
.
known
)
{
notify
<
hook
::
message_sending_failed
>
(
sender
,
receiver
,
mid
,
msg
);
notify
<
hook
::
message_sending_failed
>
(
sender
,
receiver
,
mid
,
msg
);
return
false
;
return
false
;
}
}
...
@@ -180,9 +180,14 @@ bool instance::dispatch(execution_unit* ctx, const strong_actor_ptr& sender,
...
@@ -180,9 +180,14 @@ bool instance::dispatch(execution_unit* ctx, const strong_actor_ptr& sender,
});
});
header
hdr
{
message_type
::
dispatch_message
,
0
,
0
,
mid
.
integer_value
(),
header
hdr
{
message_type
::
dispatch_message
,
0
,
0
,
mid
.
integer_value
(),
sender
?
sender
->
id
()
:
invalid_actor_id
,
receiver
->
id
()};
sender
?
sender
->
id
()
:
invalid_actor_id
,
receiver
->
id
()};
write
(
ctx
,
callee_
.
get_buffer
(
path
->
hdl
),
hdr
,
&
writer
);
if
(
lr
.
hdl
)
{
flush
(
*
path
);
auto
hdl
=
std
::
move
(
*
lr
.
hdl
);
notify
<
hook
::
message_sent
>
(
sender
,
path
->
next_hop
,
receiver
,
mid
,
msg
);
write
(
ctx
,
callee_
.
get_buffer
(
hdl
),
hdr
,
&
writer
);
flush
(
hdl
);
}
else
{
write
(
ctx
,
callee_
.
get_buffer
(
receiver
->
node
()),
hdr
,
&
writer
);
}
notify
<
hook
::
message_sent
>
(
sender
,
receiver
->
node
(),
receiver
,
mid
,
msg
);
return
true
;
return
true
;
}
}
...
@@ -296,16 +301,16 @@ bool instance::handle(execution_unit* ctx, connection_handle hdl, header& hdr,
...
@@ -296,16 +301,16 @@ bool instance::handle(execution_unit* ctx, connection_handle hdl, header& hdr,
switch
(
hdr
.
operation
)
{
switch
(
hdr
.
operation
)
{
case
message_type
:
:
server_handshake
:
{
case
message_type
:
:
server_handshake
:
{
node_id
source_node
;
node_id
source_node
;
basp
::
routing_table
::
endpoint
autoconn_addr
;
actor_id
aid
=
invalid_actor_id
;
actor_id
aid
=
invalid_actor_id
;
std
::
set
<
std
::
string
>
sigs
;
std
::
set
<
std
::
string
>
sigs
;
basp
::
routing_table
::
endpoint
autoconn_addr
;
if
(
!
payload_valid
())
{
if
(
!
payload_valid
())
{
CAF_LOG_ERROR
(
"fail to receive the app identifier"
);
CAF_LOG_ERROR
(
"fail to receive the app identifier"
);
return
false
;
return
false
;
}
else
{
}
else
{
binary_deserializer
bd
{
ctx
,
*
payload
};
binary_deserializer
bd
{
ctx
,
*
payload
};
std
::
string
remote_appid
;
std
::
string
remote_appid
;
if
(
bd
(
source_node
,
remote_appid
))
if
(
bd
(
source_node
,
remote_appid
,
autoconn_addr
))
return
false
;
return
false
;
auto
appid
=
get_or
(
callee_
.
config
(),
"middleman.app-identifier"
,
auto
appid
=
get_or
(
callee_
.
config
(),
"middleman.app-identifier"
,
defaults
::
middleman
::
app_identifier
);
defaults
::
middleman
::
app_identifier
);
...
@@ -313,7 +318,7 @@ bool instance::handle(execution_unit* ctx, connection_handle hdl, header& hdr,
...
@@ -313,7 +318,7 @@ bool instance::handle(execution_unit* ctx, connection_handle hdl, header& hdr,
CAF_LOG_ERROR
(
"app identifier mismatch"
);
CAF_LOG_ERROR
(
"app identifier mismatch"
);
return
false
;
return
false
;
}
}
if
(
bd
(
aid
,
sigs
,
autoconn_addr
))
if
(
bd
(
aid
,
sigs
))
return
false
;
return
false
;
}
}
// Close self connection immediately after handshake.
// Close self connection immediately after handshake.
...
@@ -322,29 +327,28 @@ bool instance::handle(execution_unit* ctx, connection_handle hdl, header& hdr,
...
@@ -322,29 +327,28 @@ bool instance::handle(execution_unit* ctx, connection_handle hdl, header& hdr,
callee_
.
finalize_handshake
(
source_node
,
aid
,
sigs
);
callee_
.
finalize_handshake
(
source_node
,
aid
,
sigs
);
return
false
;
return
false
;
}
}
auto
lr
=
tbl_
.
lookup
(
source_node
);
// Close redundant connections.
// Close redundant connections.
if
(
tbl_
.
lookup_direct
(
source_node
)
)
{
if
(
lr
.
hdl
)
{
CAF_LOG_DEBUG
(
"close redundant connection:"
<<
CAF_ARG
(
source_node
));
CAF_LOG_DEBUG
(
"close redundant connection:"
<<
CAF_ARG
(
source_node
));
callee_
.
finalize_handshake
(
source_node
,
aid
,
sigs
);
callee_
.
finalize_handshake
(
source_node
,
aid
,
sigs
);
return
false
;
return
false
;
}
}
// Add new route to this node.
// Add new route to this node.
CAF_LOG_DEBUG
(
"new connection:"
<<
CAF_ARG
(
source_node
));
CAF_LOG_DEBUG
(
"new connection:"
<<
CAF_ARG
(
source_node
));
tbl_
.
add_direct
(
hdl
,
source_node
);
if
(
lr
.
known
)
tbl_
.
handle
(
source_node
,
hdl
);
else
tbl_
.
add
(
source_node
,
hdl
);
// Store autoconnect address.
// Store autoconnect address.
auto
peer_server
=
system
().
registry
().
get
(
atom
(
"PeerServ"
));
auto
peer_server
=
system
().
registry
().
get
(
atom
(
"PeerServ"
));
anon_send
(
actor_cast
<
actor
>
(
peer_server
),
put_atom
::
value
,
anon_send
(
actor_cast
<
actor
>
(
peer_server
),
put_atom
::
value
,
to_string
(
source_node
),
make_message
(
std
::
move
(
autoconn_addr
)));
to_string
(
source_node
),
make_message
(
std
::
move
(
autoconn_addr
)));
// write handshake as client in response
write_client_handshake
(
ctx
,
callee_
.
get_buffer
(
hdl
));
auto
path
=
tbl_
.
lookup
(
source_node
);
flush
(
hdl
);
if
(
!
path
)
{
callee_
.
learned_new_node
(
source_node
);
CAF_LOG_ERROR
(
"no route to host after server handshake"
);
return
false
;
}
write_client_handshake
(
ctx
,
callee_
.
get_buffer
(
path
->
hdl
));
callee_
.
learned_new_node_directly
(
source_node
,
false
);
callee_
.
finalize_handshake
(
source_node
,
aid
,
sigs
);
callee_
.
finalize_handshake
(
source_node
,
aid
,
sigs
);
flush
(
*
path
);
callee_
.
send_buffered_messages
(
ctx
,
source_node
,
hdl
);
break
;
break
;
}
}
case
message_type
:
:
client_handshake
:
{
case
message_type
:
:
client_handshake
:
{
...
@@ -356,6 +360,7 @@ bool instance::handle(execution_unit* ctx, connection_handle hdl, header& hdr,
...
@@ -356,6 +360,7 @@ bool instance::handle(execution_unit* ctx, connection_handle hdl, header& hdr,
node_id
source_node
;
node_id
source_node
;
std
::
string
remote_appid
;
std
::
string
remote_appid
;
basp
::
routing_table
::
endpoint
autoconn_addr
;
basp
::
routing_table
::
endpoint
autoconn_addr
;
// TODO: Read addrs separately.
if
(
bd
(
source_node
,
remote_appid
,
autoconn_addr
))
if
(
bd
(
source_node
,
remote_appid
,
autoconn_addr
))
return
false
;
return
false
;
auto
appid
=
get_if
<
std
::
string
>
(
&
callee_
.
config
(),
auto
appid
=
get_if
<
std
::
string
>
(
&
callee_
.
config
(),
...
@@ -365,15 +370,21 @@ bool instance::handle(execution_unit* ctx, connection_handle hdl, header& hdr,
...
@@ -365,15 +370,21 @@ bool instance::handle(execution_unit* ctx, connection_handle hdl, header& hdr,
CAF_LOG_ERROR
(
"app identifier mismatch"
);
CAF_LOG_ERROR
(
"app identifier mismatch"
);
return
false
;
return
false
;
}
}
if
(
tbl_
.
lookup_direct
(
source_node
))
{
auto
lr
=
tbl_
.
lookup
(
source_node
);
if
(
lr
.
hdl
)
{
CAF_LOG_DEBUG
(
"received second client handshake:"
CAF_LOG_DEBUG
(
"received second client handshake:"
<<
CAF_ARG
(
source_node
));
<<
CAF_ARG
(
source_node
));
break
;
break
;
}
}
// Add
route to this node
.
// Add
this node to our contacts
.
CAF_LOG_DEBUG
(
"new connection:"
<<
CAF_ARG
(
source_node
));
CAF_LOG_DEBUG
(
"new connection:"
<<
CAF_ARG
(
source_node
));
tbl_
.
add_direct
(
hdl
,
source_node
);
// Either add a new node or add the handle to a known one.
callee_
.
learned_new_node_directly
(
source_node
,
false
);
if
(
lr
.
known
)
tbl_
.
handle
(
source_node
,
hdl
);
else
tbl_
.
add
(
source_node
,
hdl
);
callee_
.
learned_new_node
(
source_node
);
callee_
.
send_buffered_messages
(
ctx
,
source_node
,
hdl
);
// Store autoconnect address.
// Store autoconnect address.
auto
peer_server
=
system
().
registry
().
get
(
atom
(
"PeerServ"
));
auto
peer_server
=
system
().
registry
().
get
(
atom
(
"PeerServ"
));
anon_send
(
actor_cast
<
actor
>
(
peer_server
),
put_atom
::
value
,
anon_send
(
actor_cast
<
actor
>
(
peer_server
),
put_atom
::
value
,
...
@@ -384,7 +395,7 @@ bool instance::handle(execution_unit* ctx, connection_handle hdl, header& hdr,
...
@@ -384,7 +395,7 @@ bool instance::handle(execution_unit* ctx, connection_handle hdl, header& hdr,
// Sanity checks.
// Sanity checks.
if
(
!
payload_valid
())
if
(
!
payload_valid
())
return
false
;
return
false
;
auto
source_node
=
tbl_
.
lookup
_direct
(
hdl
);
auto
source_node
=
tbl_
.
lookup
(
hdl
);
if
(
source_node
==
none
)
{
if
(
source_node
==
none
)
{
CAF_LOG_ERROR
(
"received dispatch_message before handshake"
);
CAF_LOG_ERROR
(
"received dispatch_message before handshake"
);
return
false
;
return
false
;
...
@@ -413,7 +424,7 @@ bool instance::handle(execution_unit* ctx, connection_handle hdl, header& hdr,
...
@@ -413,7 +424,7 @@ bool instance::handle(execution_unit* ctx, connection_handle hdl, header& hdr,
break
;
break
;
}
}
case
message_type
:
:
announce_proxy
:
{
case
message_type
:
:
announce_proxy
:
{
auto
source_node
=
tbl_
.
lookup
_direct
(
hdl
);
auto
source_node
=
tbl_
.
lookup
(
hdl
);
if
(
source_node
==
none
)
{
if
(
source_node
==
none
)
{
CAF_LOG_ERROR
(
"received announce_proxy before handshake"
);
CAF_LOG_ERROR
(
"received announce_proxy before handshake"
);
return
false
;
return
false
;
...
@@ -425,7 +436,7 @@ bool instance::handle(execution_unit* ctx, connection_handle hdl, header& hdr,
...
@@ -425,7 +436,7 @@ bool instance::handle(execution_unit* ctx, connection_handle hdl, header& hdr,
// Sanity checks.
// Sanity checks.
if
(
!
payload_valid
())
if
(
!
payload_valid
())
return
false
;
return
false
;
auto
source_node
=
tbl_
.
lookup
_direct
(
hdl
);
auto
source_node
=
tbl_
.
lookup
(
hdl
);
if
(
source_node
==
none
)
{
if
(
source_node
==
none
)
{
CAF_LOG_ERROR
(
"received announce_proxy before handshake"
);
CAF_LOG_ERROR
(
"received announce_proxy before handshake"
);
return
false
;
return
false
;
...
@@ -441,7 +452,7 @@ bool instance::handle(execution_unit* ctx, connection_handle hdl, header& hdr,
...
@@ -441,7 +452,7 @@ bool instance::handle(execution_unit* ctx, connection_handle hdl, header& hdr,
break
;
break
;
}
}
case
message_type
:
:
heartbeat
:
{
case
message_type
:
:
heartbeat
:
{
auto
source_node
=
tbl_
.
lookup
_direct
(
hdl
);
auto
source_node
=
tbl_
.
lookup
(
hdl
);
if
(
source_node
==
none
)
{
if
(
source_node
==
none
)
{
CAF_LOG_ERROR
(
"received announce_proxy before handshake"
);
CAF_LOG_ERROR
(
"received announce_proxy before handshake"
);
return
false
;
return
false
;
...
...
libcaf_io/src/middleman.cpp
View file @
7bedcd63
...
@@ -389,7 +389,8 @@ void middleman::init(actor_system_config& cfg) {
...
@@ -389,7 +389,8 @@ void middleman::init(actor_system_config& cfg) {
.
add_message_type
<
accept_handle
>
(
"@accept_handle"
)
.
add_message_type
<
accept_handle
>
(
"@accept_handle"
)
.
add_message_type
<
connection_handle
>
(
"@connection_handle"
)
.
add_message_type
<
connection_handle
>
(
"@connection_handle"
)
.
add_message_type
<
connection_passivated_msg
>
(
"@connection_passivated_msg"
)
.
add_message_type
<
connection_passivated_msg
>
(
"@connection_passivated_msg"
)
.
add_message_type
<
acceptor_passivated_msg
>
(
"@acceptor_passivated_msg"
);
.
add_message_type
<
acceptor_passivated_msg
>
(
"@acceptor_passivated_msg"
)
.
add_message_type
<
basp
::
routing_table
::
endpoint
>
(
"@autoconnect_endpoint"
);
// compute and set ID for this network node
// compute and set ID for this network node
node_id
this_node
{
node_id
::
data
::
create_singleton
()};
node_id
this_node
{
node_id
::
data
::
create_singleton
()};
system
().
node_
.
swap
(
this_node
);
system
().
node_
.
swap
(
this_node
);
...
...
libcaf_io/src/routing_table.cpp
View file @
7bedcd63
...
@@ -33,123 +33,87 @@ routing_table::~routing_table() {
...
@@ -33,123 +33,87 @@ routing_table::~routing_table() {
// nop
// nop
}
}
optional
<
routing_table
::
route
>
routing_table
::
lookup
(
const
node_id
&
target
)
{
node_id
routing_table
::
lookup
(
const
connection_handle
&
hdl
)
const
{
auto
hdl
=
lookup_direct
(
target
);
return
get_opt
(
nid_by_hdl_
,
hdl
,
none
);
if
(
hdl
)
return
route
{
target
,
*
hdl
};
// pick first available indirect route
auto
i
=
indirect_
.
find
(
target
);
if
(
i
!=
indirect_
.
end
())
{
auto
&
hops
=
i
->
second
;
while
(
!
hops
.
empty
())
{
auto
&
hop
=
*
hops
.
begin
();
hdl
=
lookup_direct
(
hop
);
if
(
hdl
)
return
route
{
hop
,
*
hdl
};
hops
.
erase
(
hops
.
begin
());
}
}
return
none
;
}
}
node_id
routing_table
::
lookup_direct
(
const
connection_handle
&
hdl
)
const
{
routing_table
::
lookup_result
routing_table
::
lookup
(
const
node_id
&
nid
)
const
{
return
get_opt
(
direct_by_hdl_
,
hdl
,
none
);
auto
i
=
node_information_base_
.
find
(
nid
);
if
(
i
!=
node_information_base_
.
end
())
return
{
true
,
i
->
second
.
hdl
};
return
{
false
,
none
};
}
}
optional
<
connection_handle
>
void
routing_table
::
erase
(
const
connection_handle
&
hdl
,
erase_callback
&
cb
)
{
routing_table
::
lookup_direct
(
const
node_id
&
nid
)
const
{
auto
i
=
nid_by_hdl_
.
find
(
hdl
);
auto
i
=
direct_by_nid_
.
find
(
nid
);
if
(
i
==
nid_by_hdl_
.
end
())
if
(
i
!=
direct_by_nid_
.
end
())
return
;
return
i
->
second
;
cb
(
i
->
second
);
return
none
;
parent_
->
parent
().
notify
<
hook
::
connection_lost
>
(
i
->
second
);
node_information_base_
.
erase
(
i
->
second
);
nid_by_hdl_
.
erase
(
i
->
first
);
// TODO: Look through other nodes and remove this one as an origin?
}
}
node_id
routing_table
::
lookup_indirect
(
const
node_id
&
nid
)
const
{
void
routing_table
::
add
(
const
node_id
&
nid
,
const
connection_handle
&
hdl
)
{
auto
i
=
indirect_
.
find
(
nid
);
CAF_ASSERT
(
nid_by_hdl_
.
count
(
hdl
)
==
0
);
if
(
i
==
indirect_
.
end
())
CAF_ASSERT
(
node_information_base_
.
count
(
nid
)
==
0
);
return
none
;
nid_by_hdl_
.
emplace
(
hdl
,
nid
);
if
(
i
->
second
.
empty
())
node_information_base_
[
nid
]
=
node_info
{
hdl
,
none
};
return
none
;
parent_
->
parent
().
notify
<
hook
::
new_connection_established
>
(
nid
);
return
*
i
->
second
.
begin
();
}
}
void
routing_table
::
blacklist
(
const
node_id
&
hop
,
const
node_id
&
dest
)
{
void
routing_table
::
add
(
const
node_id
&
nid
,
const
node_id
&
origin
)
{
blacklist_
[
dest
].
emplace
(
hop
);
CAF_ASSERT
(
node_information_base_
.
count
(
nid
)
==
0
);
auto
i
=
indirect_
.
find
(
dest
);
node_information_base_
[
nid
]
=
node_info
{
none
,
origin
};
if
(
i
==
indirect_
.
end
())
// TODO: Some new related hook?
return
;
//parent_->parent().notify<hook::new_connection_established>(nid);
i
->
second
.
erase
(
hop
);
if
(
i
->
second
.
empty
())
indirect_
.
erase
(
i
);
}
}
void
routing_table
::
erase_direct
(
const
connection_handle
&
hdl
,
void
routing_table
::
add
(
const
node_id
&
nid
)
{
erase_callback
&
cb
)
{
//CAF_ASSERT(hdl_by_nid_.count(nid) == 0);
auto
i
=
direct_by_hdl_
.
find
(
hdl
);
CAF_ASSERT
(
node_information_base_
.
count
(
nid
)
==
0
);
if
(
i
==
direct_by_hdl_
.
end
())
node_information_base_
[
nid
]
=
node_info
{
none
,
none
};
return
;
// TODO: Some new related hook?
cb
(
i
->
second
);
//parent_->parent().notify<hook::new_connection_established>(nid);
parent_
->
parent
().
notify
<
hook
::
connection_lost
>
(
i
->
second
);
direct_by_nid_
.
erase
(
i
->
second
);
direct_by_hdl_
.
erase
(
i
->
first
);
}
}
bool
routing_table
::
erase_indirect
(
const
node_id
&
dest
)
{
bool
routing_table
::
reachable
(
const
node_id
&
dest
)
{
auto
i
=
indirect_
.
find
(
dest
);
auto
i
=
node_information_base_
.
find
(
dest
);
if
(
i
==
indirect_
.
end
())
if
(
i
!=
node_information_base_
.
end
())
return
false
;
return
i
->
second
.
hdl
!=
none
;
if
(
parent_
->
parent
().
has_hook
())
return
false
;
for
(
auto
&
nid
:
i
->
second
)
parent_
->
parent
().
notify
<
hook
::
route_lost
>
(
nid
,
dest
);
indirect_
.
erase
(
i
);
return
true
;
}
}
void
routing_table
::
add_direct
(
const
connection_handle
&
hdl
,
bool
routing_table
::
origin
(
const
node_id
&
nid
,
const
node_id
&
origin
)
{
const
node_id
&
nid
)
{
auto
i
=
node_information_base_
.
find
(
nid
);
CAF_ASSERT
(
direct_by_hdl_
.
count
(
hdl
)
==
0
);
if
(
i
==
node_information_base_
.
end
())
CAF_ASSERT
(
direct_by_nid_
.
count
(
nid
)
==
0
);
return
false
;
direct_by_hdl_
.
emplace
(
hdl
,
nid
);
i
->
second
.
origin
=
origin
;
direct_by_nid_
.
emplace
(
nid
,
hdl
);
return
true
;
parent_
->
parent
().
notify
<
hook
::
new_connection_established
>
(
nid
);
}
}
bool
routing_table
::
add_indirect
(
const
node_id
&
hop
,
const
node_id
&
dest
)
{
optional
<
node_id
>
routing_table
::
origin
(
const
node_id
&
nid
)
{
auto
i
=
blacklist_
.
find
(
dest
);
auto
i
=
node_information_base_
.
find
(
nid
);
if
(
i
==
blacklist_
.
end
()
||
i
->
second
.
count
(
hop
)
==
0
)
{
if
(
i
==
node_information_base_
.
end
())
auto
&
hops
=
indirect_
[
dest
];
return
none
;
auto
added_first
=
hops
.
empty
();
return
i
->
second
.
origin
;
hops
.
emplace
(
hop
);
parent_
->
parent
().
notify
<
hook
::
new_route_added
>
(
hop
,
dest
);
return
added_first
;
}
return
false
;
// blacklisted
}
}
bool
routing_table
::
reachable
(
const
node_id
&
dest
)
{
bool
routing_table
::
handle
(
const
node_id
&
nid
,
const
connection_handle
&
hdl
)
{
return
direct_by_nid_
.
count
(
dest
)
>
0
||
indirect_
.
count
(
dest
)
>
0
;
auto
i
=
node_information_base_
.
find
(
nid
);
if
(
i
==
node_information_base_
.
end
())
return
false
;
i
->
second
.
hdl
=
hdl
;
nid_by_hdl_
.
emplace
(
hdl
,
nid
);
return
true
;
}
}
size_t
routing_table
::
erase
(
const
node_id
&
dest
,
erase_callback
&
cb
)
{
optional
<
connection_handle
>
routing_table
::
handle
(
const
node_id
&
nid
)
{
cb
(
dest
);
auto
i
=
node_information_base_
.
find
(
nid
);
size_t
res
=
0
;
if
(
i
==
node_information_base_
.
end
())
auto
i
=
indirect_
.
find
(
dest
);
return
none
;
if
(
i
!=
indirect_
.
end
())
{
return
i
->
second
.
hdl
;
res
=
i
->
second
.
size
();
for
(
auto
&
nid
:
i
->
second
)
{
cb
(
nid
);
parent_
->
parent
().
notify
<
hook
::
route_lost
>
(
nid
,
dest
);
}
indirect_
.
erase
(
i
);
}
auto
hdl
=
lookup_direct
(
dest
);
if
(
hdl
)
{
direct_by_hdl_
.
erase
(
*
hdl
);
direct_by_nid_
.
erase
(
dest
);
parent_
->
parent
().
notify
<
hook
::
connection_lost
>
(
dest
);
++
res
;
}
return
res
;
}
}
const
routing_table
::
endpoint
&
routing_table
::
autoconnect_endpoint
()
{
const
routing_table
::
endpoint
&
routing_table
::
autoconnect_endpoint
()
{
...
...
libcaf_io/test/automatic_connection.cpp
View file @
7bedcd63
This diff is collapsed.
Click to expand it.
libcaf_io/test/basp.cpp
View file @
7bedcd63
...
@@ -75,7 +75,6 @@ constexpr uint64_t default_operation_data = make_message_id().integer_value();
...
@@ -75,7 +75,6 @@ constexpr uint64_t default_operation_data = make_message_id().integer_value();
constexpr
auto
basp_atom
=
caf
::
atom
(
"BASP"
);
constexpr
auto
basp_atom
=
caf
::
atom
(
"BASP"
);
constexpr
auto
spawn_serv_atom
=
caf
::
atom
(
"SpawnServ"
);
constexpr
auto
spawn_serv_atom
=
caf
::
atom
(
"SpawnServ"
);
constexpr
auto
config_serv_atom
=
caf
::
atom
(
"ConfigServ"
);
}
// namespace <anonymous>
}
// namespace <anonymous>
...
@@ -290,9 +289,9 @@ public:
...
@@ -290,9 +289,9 @@ public:
make_message
(
sys_atom
::
value
,
get_atom
::
value
,
"info"
));
make_message
(
sys_atom
::
value
,
get_atom
::
value
,
"info"
));
// test whether basp instance correctly updates the
// test whether basp instance correctly updates the
// routing table upon receiving client handshakes
// routing table upon receiving client handshakes
auto
path
=
unbox
(
tbl
().
lookup
(
n
.
id
)
);
auto
lr
=
tbl
().
lookup
(
n
.
id
);
CAF_
CHECK_EQUAL
(
path
.
hdl
,
n
.
connection
);
CAF_
REQUIRE
(
lr
.
hdl
);
CAF_CHECK_EQUAL
(
path
.
next_hop
,
n
.
id
);
CAF_CHECK_EQUAL
(
*
lr
.
hdl
,
n
.
connection
);
}
}
std
::
pair
<
basp
::
header
,
buffer
>
read_from_out_buf
(
connection_handle
hdl
)
{
std
::
pair
<
basp
::
header
,
buffer
>
read_from_out_buf
(
connection_handle
hdl
)
{
...
@@ -568,8 +567,8 @@ CAF_TEST(remote_actor_and_send) {
...
@@ -568,8 +567,8 @@ CAF_TEST(remote_actor_and_send) {
mock
(
jupiter
().
connection
,
mock
(
jupiter
().
connection
,
{
basp
::
message_type
::
server_handshake
,
0
,
0
,
basp
::
version
,
{
basp
::
message_type
::
server_handshake
,
0
,
0
,
basp
::
version
,
jupiter
().
dummy_actor
->
id
(),
invalid_actor_id
},
jupiter
().
dummy_actor
->
id
(),
invalid_actor_id
},
jupiter
().
id
,
std
::
string
{},
jupiter
().
dummy_actor
->
id
(),
uint32_t
{
0
},
jupiter
().
id
,
std
::
string
{},
basp
::
routing_table
::
endpoint
{
},
basp
::
routing_table
::
endpoint
{
})
jupiter
().
dummy_actor
->
id
(),
uint32_t
{
0
})
.
receive
(
jupiter
().
connection
,
basp
::
message_type
::
client_handshake
,
.
receive
(
jupiter
().
connection
,
basp
::
message_type
::
client_handshake
,
no_flags
,
any_vals
,
no_operation_data
,
invalid_actor_id
,
no_flags
,
any_vals
,
no_operation_data
,
invalid_actor_id
,
invalid_actor_id
,
this_node
(),
std
::
string
{},
invalid_actor_id
,
this_node
(),
std
::
string
{},
...
@@ -660,106 +659,10 @@ CAF_TEST_FIXTURE_SCOPE_END()
...
@@ -660,106 +659,10 @@ CAF_TEST_FIXTURE_SCOPE_END()
CAF_TEST_FIXTURE_SCOPE
(
basp_tests_with_autoconn
,
autoconn_enabled_fixture
)
CAF_TEST_FIXTURE_SCOPE
(
basp_tests_with_autoconn
,
autoconn_enabled_fixture
)
CAF_TEST_DISABLED
(
automatic_connection
)
{
// this tells our BASP broker to enable the automatic connection feature
//anon_send(aut(), ok_atom::value,
// "middleman.enable-automatic-connections", make_message(true));
//mpx()->exec_runnable(); // process publish message in basp_broker
// jupiter [remote hdl 0] -> mars [remote hdl 1] -> earth [this_node]
// (this node receives a message from jupiter via mars and responds via mars,
// but then also establishes a connection to jupiter directly)
auto
check_node_in_tbl
=
[
&
](
node
&
n
)
{
auto
hdl
=
tbl
().
lookup_direct
(
n
.
id
);
CAF_REQUIRE
(
hdl
);
};
mpx
()
->
provide_scribe
(
"jupiter"
,
8080
,
jupiter
().
connection
);
CAF_CHECK
(
mpx
()
->
has_pending_scribe
(
"jupiter"
,
8080
));
CAF_MESSAGE
(
"self: "
<<
to_string
(
self
()
->
address
()));
auto
ax
=
accept_handle
::
from_int
(
4242
);
mpx
()
->
provide_acceptor
(
4242
,
ax
);
publish
(
self
(),
4242
);
mpx
()
->
flush_runnables
();
// process publish message in basp_broker
CAF_MESSAGE
(
"connect to mars"
);
connect_node
(
mars
(),
ax
,
self
()
->
id
());
//CAF_CHECK_EQUAL(tbl().lookup_direct(mars().id).id(), mars().connection.id());
check_node_in_tbl
(
mars
());
// TODO: this use case is no longer possible. Nodes are required to open a
// connection first, before sending messages (forwarding has been
// removed).
CAF_MESSAGE
(
"simulate that an actor from jupiter "
"sends a message to us via mars"
);
mock
(
mars
().
connection
,
{
basp
::
message_type
::
dispatch_message
,
0
,
0
,
0
,
jupiter
().
dummy_actor
->
id
(),
self
()
->
id
()},
std
::
vector
<
actor_id
>
{},
make_message
(
"hello from jupiter!"
))
.
receive
(
mars
().
connection
,
basp
::
message_type
::
dispatch_message
,
basp
::
header
::
named_receiver_flag
,
any_vals
,
default_operation_data
,
any_vals
,
invalid_actor_id
,
spawn_serv_atom
,
std
::
vector
<
actor_id
>
{},
make_message
(
sys_atom
::
value
,
get_atom
::
value
,
"info"
))
.
receive
(
mars
().
connection
,
basp
::
message_type
::
dispatch_message
,
basp
::
header
::
named_receiver_flag
,
any_vals
,
default_operation_data
,
any_vals
,
// actor ID of an actor spawned by the BASP broker
invalid_actor_id
,
config_serv_atom
,
std
::
vector
<
actor_id
>
{},
make_message
(
get_atom
::
value
,
"basp.default-connectivity-tcp"
))
.
receive
(
mars
().
connection
,
basp
::
message_type
::
announce_proxy
,
no_flags
,
no_payload
,
no_operation_data
,
invalid_actor_id
,
jupiter
().
dummy_actor
->
id
());
CAF_CHECK_EQUAL
(
mpx
()
->
output_buffer
(
mars
().
connection
).
size
(),
0u
);
CAF_CHECK_EQUAL
(
tbl
().
lookup_indirect
(
jupiter
().
id
),
mars
().
id
);
CAF_CHECK_EQUAL
(
tbl
().
lookup_indirect
(
mars
().
id
),
none
);
auto
connection_helper_actor
=
sys
.
latest_actor_id
();
CAF_CHECK_EQUAL
(
mpx
()
->
output_buffer
(
mars
().
connection
).
size
(),
0u
);
// create a dummy config server and respond to the name lookup
CAF_MESSAGE
(
"receive ConfigServ of jupiter"
);
network
::
address_listing
res
;
res
[
network
::
protocol
::
ipv4
].
emplace_back
(
"jupiter"
);
mock
(
mars
().
connection
,
{
basp
::
message_type
::
dispatch_message
,
0
,
0
,
0
,
invalid_actor_id
,
connection_helper_actor
},
std
::
vector
<
actor_id
>
{},
make_message
(
"basp.default-connectivity-tcp"
,
make_message
(
uint16_t
{
8080
},
std
::
move
(
res
))));
// our connection helper should now connect to jupiter and
// send the scribe handle over to the BASP broker
while
(
mpx
()
->
has_pending_scribe
(
"jupiter"
,
8080
))
{
sched
.
run
();
mpx
()
->
flush_runnables
();
}
CAF_REQUIRE
(
mpx
()
->
output_buffer
(
mars
().
connection
).
empty
());
// send handshake from jupiter
mock
(
jupiter
().
connection
,
{
basp
::
message_type
::
server_handshake
,
0
,
0
,
basp
::
version
,
jupiter
().
dummy_actor
->
id
(),
invalid_actor_id
},
std
::
string
{},
jupiter
().
dummy_actor
->
id
(),
uint32_t
{
0
})
.
receive
(
jupiter
().
connection
,
basp
::
message_type
::
client_handshake
,
no_flags
,
1u
,
no_operation_data
,
invalid_actor_id
,
invalid_actor_id
,
std
::
string
{});
CAF_CHECK_EQUAL
(
tbl
().
lookup_indirect
(
jupiter
().
id
),
none
);
CAF_CHECK_EQUAL
(
tbl
().
lookup_indirect
(
mars
().
id
),
none
);
check_node_in_tbl
(
jupiter
());
check_node_in_tbl
(
mars
());
CAF_MESSAGE
(
"receive message from jupiter"
);
self
()
->
receive
(
[](
const
std
::
string
&
str
)
->
std
::
string
{
CAF_CHECK_EQUAL
(
str
,
"hello from jupiter!"
);
return
"hello from earth!"
;
}
);
mpx
()
->
exec_runnable
();
// process forwarded message in basp_broker
CAF_MESSAGE
(
"response message must take direct route now"
);
mock
().
receive
(
jupiter
().
connection
,
basp
::
message_type
::
dispatch_message
,
no_flags
,
any_vals
,
default_operation_data
,
self
()
->
id
(),
jupiter
().
dummy_actor
->
id
(),
std
::
vector
<
actor_id
>
{},
make_message
(
"hello from earth!"
));
CAF_CHECK_EQUAL
(
mpx
()
->
output_buffer
(
mars
().
connection
).
size
(),
0u
);
}
CAF_TEST
(
read_address_after_handshake
)
{
CAF_TEST
(
read_address_after_handshake
)
{
auto
check_node_in_tbl
=
[
&
](
node
&
n
)
{
auto
check_node_in_tbl
=
[
&
](
node
&
n
)
{
auto
hdl
=
tbl
().
lookup_direct
(
n
.
id
);
auto
lr
=
tbl
().
lookup
(
n
.
id
);
CAF_REQUIRE
(
hdl
);
CAF_REQUIRE
(
lr
.
hdl
);
};
};
mpx
()
->
provide_scribe
(
"jupiter"
,
8080
,
jupiter
().
connection
);
mpx
()
->
provide_scribe
(
"jupiter"
,
8080
,
jupiter
().
connection
);
CAF_CHECK
(
mpx
()
->
has_pending_scribe
(
"jupiter"
,
8080
));
CAF_CHECK
(
mpx
()
->
has_pending_scribe
(
"jupiter"
,
8080
));
...
...
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