Commit d8842778 authored by Dominik Charousset's avatar Dominik Charousset

Implement send-to-named-actor feature in BASP

parent 873e85e1
doc/announce_proxy_instance.png

37.9 KB | W: | H:

doc/announce_proxy_instance.png

207 KB | W: | H:

doc/announce_proxy_instance.png
doc/announce_proxy_instance.png
doc/announce_proxy_instance.png
doc/announce_proxy_instance.png
  • 2-up
  • Swipe
  • Onion skin
No preview for this file type
doc/basp_header.png

76.8 KB | W: | H:

doc/basp_header.png

219 KB | W: | H:

doc/basp_header.png
doc/basp_header.png
doc/basp_header.png
doc/basp_header.png
  • 2-up
  • Swipe
  • Onion skin
doc/client_handshake.png

35.8 KB | W: | H:

doc/client_handshake.png

213 KB | W: | H:

doc/client_handshake.png
doc/client_handshake.png
doc/client_handshake.png
doc/client_handshake.png
  • 2-up
  • Swipe
  • Onion skin
doc/dispatch_message.png

47 KB | W: | H:

doc/dispatch_message.png

285 KB | W: | H:

doc/dispatch_message.png
doc/dispatch_message.png
doc/dispatch_message.png
doc/dispatch_message.png
  • 2-up
  • Swipe
  • Onion skin
doc/kill_proxy_instance.png

39.3 KB | W: | H:

doc/kill_proxy_instance.png

212 KB | W: | H:

doc/kill_proxy_instance.png
doc/kill_proxy_instance.png
doc/kill_proxy_instance.png
doc/kill_proxy_instance.png
  • 2-up
  • Swipe
  • Onion skin
doc/server_handshake.png

44.1 KB | W: | H:

doc/server_handshake.png

243 KB | W: | H:

doc/server_handshake.png
doc/server_handshake.png
doc/server_handshake.png
doc/server_handshake.png
  • 2-up
  • Swipe
  • Onion skin
...@@ -456,6 +456,8 @@ private: ...@@ -456,6 +456,8 @@ private:
opencl::manager* opencl_manager_; opencl::manager* opencl_manager_;
riac::probe* probe_; riac::probe* probe_;
bool await_actors_before_shutdown_; bool await_actors_before_shutdown_;
strong_actor_ptr config_serv_;
strong_actor_ptr spawn_serv_;
}; };
} // namespace caf } // namespace caf
......
...@@ -144,151 +144,12 @@ auto actor_registry::named_actors() const -> name_map { ...@@ -144,151 +144,12 @@ auto actor_registry::named_actors() const -> name_map {
return named_entries_; return named_entries_;
} }
namespace {
struct kvstate {
using key_type = std::string;
using mapped_type = message;
using subscriber_set = std::unordered_set<strong_actor_ptr>;
using topic_set = std::unordered_set<std::string>;
std::unordered_map<key_type, std::pair<mapped_type, subscriber_set>> data;
std::unordered_map<strong_actor_ptr, topic_set> subscribers;
const char* name = "caf.config_server";
template <class Processor>
friend void serialize(Processor& proc, kvstate& x, const unsigned int) {
proc & x.data;
proc & x.subscribers;
}
};
} // namespace <anonymous>
void actor_registry::start() { void actor_registry::start() {
auto kvstore = [](stateful_actor<kvstate>* self) -> behavior { // nop
CAF_LOG_TRACE("");
std::string wildcard = "*";
auto unsubscribe_all = [=](actor subscriber) {
auto& subscribers = self->state.subscribers;
auto ptr = actor_cast<strong_actor_ptr>(subscriber);
auto i = subscribers.find(ptr);
if (i == subscribers.end())
return;
for (auto& key : i->second)
self->state.data[key].second.erase(ptr);
subscribers.erase(i);
};
self->set_down_handler([=](down_msg& dm) {
CAF_LOG_TRACE(CAF_ARG(dm));
auto ptr = actor_cast<strong_actor_ptr>(dm.source);
if (ptr)
unsubscribe_all(actor_cast<actor>(std::move(ptr)));
});
return {
[=](put_atom, const std::string& key, message& msg) {
CAF_LOG_TRACE(CAF_ARG(key) << CAF_ARG(msg));
if (key == "*")
return;
auto& vp = self->state.data[key];
vp.first = std::move(msg);
for (auto& subscriber_ptr : vp.second) {
// we never put a nullptr in our map
auto subscriber = actor_cast<actor>(subscriber_ptr);
if (subscriber != self->current_sender())
self->send(subscriber, update_atom::value, key, vp.second);
}
// also iterate all subscribers for '*'
for (auto& subscriber : self->state.data[wildcard].second)
if (subscriber != self->current_sender())
self->send(actor_cast<actor>(subscriber), update_atom::value,
key, vp.second);
},
[=](get_atom, std::string& key) -> message {
CAF_LOG_TRACE(CAF_ARG(key));
if (key == wildcard) {
std::vector<std::pair<std::string, message>> msgs;
for (auto& kvp : self->state.data)
if (kvp.first != "*")
msgs.emplace_back(kvp.first, kvp.second.first);
return make_message(ok_atom::value, std::move(msgs));
}
auto i = self->state.data.find(key);
return make_message(ok_atom::value, std::move(key),
i != self->state.data.end() ? i->second.first
: make_message());
},
[=](subscribe_atom, const std::string& key) {
auto subscriber = actor_cast<strong_actor_ptr>(self->current_sender());
CAF_LOG_TRACE(CAF_ARG(key) << CAF_ARG(subscriber));
if (! subscriber)
return;
self->state.data[key].second.insert(subscriber);
auto& subscribers = self->state.subscribers;
auto i = subscribers.find(subscriber);
if (i != subscribers.end()) {
i->second.insert(key);
} else {
self->monitor(subscriber);
subscribers.emplace(subscriber, kvstate::topic_set{key});
}
},
[=](unsubscribe_atom, const std::string& key) {
auto subscriber = actor_cast<strong_actor_ptr>(self->current_sender());
if (! subscriber)
return;
CAF_LOG_TRACE(CAF_ARG(key) << CAF_ARG(subscriber));
if (key == wildcard) {
unsubscribe_all(actor_cast<actor>(std::move(subscriber)));
return;
}
self->state.subscribers[subscriber].erase(key);
self->state.data[key].second.erase(subscriber);
}
};
};
auto spawn_serv = [](event_based_actor* self) -> behavior {
CAF_LOG_TRACE("");
return {
[=](get_atom, const std::string& name, message& args)
-> result<ok_atom, strong_actor_ptr, std::set<std::string>> {
CAF_LOG_TRACE(CAF_ARG(name) << CAF_ARG(args));
actor_config cfg{self->context()};
auto res = self->system().types().make_actor(name, cfg, args);
if (! res.first)
return sec::cannot_spawn_actor_from_arguments;
return {ok_atom::value, res.first, res.second};
}
};
};
// NOTE: all actors that we spawn here *must not* access the scheduler,
// because the scheduler will make sure that the registry is running
// as part of its initialization; hence, all actors have to
// use the lazy_init flag
//named_entries_.emplace(atom("SpawnServ"), system_.spawn_announce_actor_type_server());
auto cs = system_.spawn<hidden+lazy_init>(kvstore);
put(atom("ConfigServ"), actor_cast<strong_actor_ptr>(std::move(cs)));
auto ss = system_.spawn<hidden+lazy_init>(spawn_serv);
put(atom("SpawnServ"), actor_cast<strong_actor_ptr>(std::move(ss)));
} }
void actor_registry::stop() { void actor_registry::stop() {
class dropping_execution_unit : public execution_unit {
public:
dropping_execution_unit(actor_system* sys) : execution_unit(sys) {
// nop // nop
}
void exec_later(resumable*) override {
// should not happen in the first place
CAF_LOG_ERROR("actor registry actor called exec_later during shutdown");
}
};
// the scheduler is already stopped -> invoke exit messages manually
dropping_execution_unit dummy{&system_};
for (auto& kvp : named_entries_) {
auto mp = mailbox_element::make(nullptr, invalid_message_id, {},
exit_msg{kvp.second->address(),
exit_reason::kill});
auto ptr = static_cast<local_actor*>(actor_cast<abstract_actor*>(kvp.second));
ptr->exec_single_event(&dummy, mp);
}
named_entries_.clear();
} }
} // namespace caf } // namespace caf
...@@ -19,7 +19,10 @@ ...@@ -19,7 +19,10 @@
#include "caf/actor_system.hpp" #include "caf/actor_system.hpp"
#include <unordered_set>
#include "caf/send.hpp" #include "caf/send.hpp"
#include "caf/event_based_actor.hpp"
#include "caf/actor_system_config.hpp" #include "caf/actor_system_config.hpp"
#include "caf/policy/work_sharing.hpp" #include "caf/policy/work_sharing.hpp"
...@@ -31,6 +34,134 @@ ...@@ -31,6 +34,134 @@
namespace caf { namespace caf {
namespace {
struct kvstate {
using key_type = std::string;
using mapped_type = message;
using subscriber_set = std::unordered_set<strong_actor_ptr>;
using topic_set = std::unordered_set<std::string>;
std::unordered_map<key_type, std::pair<mapped_type, subscriber_set>> data;
std::unordered_map<strong_actor_ptr, topic_set> subscribers;
const char* name = "caf.config_server";
template <class Processor>
friend void serialize(Processor& proc, kvstate& x, const unsigned int) {
proc & x.data;
proc & x.subscribers;
}
};
behavior config_serv_impl(stateful_actor<kvstate>* self) {
CAF_LOG_TRACE("");
std::string wildcard = "*";
auto unsubscribe_all = [=](actor subscriber) {
auto& subscribers = self->state.subscribers;
auto ptr = actor_cast<strong_actor_ptr>(subscriber);
auto i = subscribers.find(ptr);
if (i == subscribers.end())
return;
for (auto& key : i->second)
self->state.data[key].second.erase(ptr);
subscribers.erase(i);
};
self->set_down_handler([=](down_msg& dm) {
CAF_LOG_TRACE(CAF_ARG(dm));
auto ptr = actor_cast<strong_actor_ptr>(dm.source);
if (ptr)
unsubscribe_all(actor_cast<actor>(std::move(ptr)));
});
return {
[=](put_atom, const std::string& key, message& msg) {
CAF_LOG_TRACE(CAF_ARG(key) << CAF_ARG(msg));
if (key == "*")
return;
auto& vp = self->state.data[key];
vp.first = std::move(msg);
for (auto& subscriber_ptr : vp.second) {
// we never put a nullptr in our map
auto subscriber = actor_cast<actor>(subscriber_ptr);
if (subscriber != self->current_sender())
self->send(subscriber, update_atom::value, key, vp.second);
}
// also iterate all subscribers for '*'
for (auto& subscriber : self->state.data[wildcard].second)
if (subscriber != self->current_sender())
self->send(actor_cast<actor>(subscriber), update_atom::value,
key, vp.second);
},
[=](get_atom, std::string& key) -> message {
CAF_LOG_TRACE(CAF_ARG(key));
if (key == wildcard) {
std::vector<std::pair<std::string, message>> msgs;
for (auto& kvp : self->state.data)
if (kvp.first != "*")
msgs.emplace_back(kvp.first, kvp.second.first);
return make_message(ok_atom::value, std::move(msgs));
}
auto i = self->state.data.find(key);
return make_message(ok_atom::value, std::move(key),
i != self->state.data.end() ? i->second.first
: make_message());
},
[=](subscribe_atom, const std::string& key) {
auto subscriber = actor_cast<strong_actor_ptr>(self->current_sender());
CAF_LOG_TRACE(CAF_ARG(key) << CAF_ARG(subscriber));
if (! subscriber)
return;
self->state.data[key].second.insert(subscriber);
auto& subscribers = self->state.subscribers;
auto i = subscribers.find(subscriber);
if (i != subscribers.end()) {
i->second.insert(key);
} else {
self->monitor(subscriber);
subscribers.emplace(subscriber, kvstate::topic_set{key});
}
},
[=](unsubscribe_atom, const std::string& key) {
auto subscriber = actor_cast<strong_actor_ptr>(self->current_sender());
if (! subscriber)
return;
CAF_LOG_TRACE(CAF_ARG(key) << CAF_ARG(subscriber));
if (key == wildcard) {
unsubscribe_all(actor_cast<actor>(std::move(subscriber)));
return;
}
self->state.subscribers[subscriber].erase(key);
self->state.data[key].second.erase(subscriber);
}
};
}
behavior spawn_serv_impl(event_based_actor* self) {
CAF_LOG_TRACE("");
return {
[=](get_atom, const std::string& name, message& args)
-> result<ok_atom, strong_actor_ptr, std::set<std::string>> {
CAF_LOG_TRACE(CAF_ARG(name) << CAF_ARG(args));
actor_config cfg{self->context()};
auto res = self->system().types().make_actor(name, cfg, args);
if (! res.first)
return sec::cannot_spawn_actor_from_arguments;
return {ok_atom::value, res.first, res.second};
}
};
}
class dropping_execution_unit : public execution_unit {
public:
dropping_execution_unit(actor_system* sys) : execution_unit(sys) {
// nop
}
void exec_later(resumable*) override {
// should not happen in the first place
CAF_LOG_ERROR("actor registry actor called exec_later during shutdown");
}
};
} // namespace <anonymous>
actor_system::module::~module() { actor_system::module::~module() {
// nop // nop
} }
...@@ -125,22 +256,31 @@ actor_system::actor_system(actor_system_config&& cfg) ...@@ -125,22 +256,31 @@ actor_system::actor_system(actor_system_config&& cfg)
types_.error_renderers_ = std::move(cfg.error_renderers_); types_.error_renderers_ = std::move(cfg.error_renderers_);
// move remaining config // move remaining config
node_.swap(cfg.network_id); node_.swap(cfg.network_id);
// spawn config and spawn servers (lazily to not access the scheduler yet)
static constexpr auto Flags = hidden + lazy_init;
spawn_serv_ = actor_cast<strong_actor_ptr>(spawn<Flags>(spawn_serv_impl));
config_serv_ = actor_cast<strong_actor_ptr>(spawn<Flags>(config_serv_impl));
// fire up remaining modules // fire up remaining modules
logger_.start(); logger_.start();
registry_.start(); registry_.start();
registry_.put(atom("SpawnServ"), spawn_serv_);
registry_.put(atom("ConfigServ"), config_serv_);
for (auto& mod : modules_) for (auto& mod : modules_)
if (mod) if (mod)
mod->start(); mod->start();
groups_.start(); groups_.start();
// store config parameters in ConfigServ
auto cs = actor_cast<actor>(registry_.get(atom("ConfigServ")));
anon_send(cs, put_atom::value, "middleman.enable-automatic-connections",
make_message(cfg.middleman_enable_automatic_connections));
} }
actor_system::~actor_system() { actor_system::~actor_system() {
if (await_actors_before_shutdown_) if (await_actors_before_shutdown_)
await_all_actors_done(); await_all_actors_done();
// shutdown system-level servers
anon_send_exit(spawn_serv_, exit_reason::user_shutdown);
anon_send_exit(config_serv_, exit_reason::user_shutdown);
// release memory as soon as possible
spawn_serv_ = nullptr;
config_serv_ = nullptr;
// group module is the first one, relies on MM
groups_.stop(); groups_.stop();
// stop modules in reverse order // stop modules in reverse order
for (auto i = modules_.rbegin(); i != modules_.rend(); ++i) for (auto i = modules_.rbegin(); i != modules_.rend(); ++i)
......
...@@ -39,24 +39,56 @@ namespace basp { ...@@ -39,24 +39,56 @@ namespace basp {
/// message types consist of only a header. /// message types consist of only a header.
struct header { struct header {
message_type operation; message_type operation;
uint8_t padding1;
uint8_t padding2;
uint8_t flags;
uint32_t payload_len; uint32_t payload_len;
uint64_t operation_data; uint64_t operation_data;
node_id source_node; node_id source_node;
node_id dest_node; node_id dest_node;
actor_id source_actor; actor_id source_actor;
actor_id dest_actor; actor_id dest_actor;
inline header(message_type m_operation, uint8_t m_flags,
uint32_t m_payload_len, uint64_t m_operation_data,
node_id m_source_node, node_id m_dest_node,
actor_id m_source_actor, actor_id m_dest_actor)
: operation(m_operation),
flags(m_flags),
payload_len(m_payload_len),
operation_data(m_operation_data),
source_node(std::move(m_source_node)),
dest_node(std::move(m_dest_node)),
source_actor(m_source_actor),
dest_actor(m_dest_actor) {
// nop
}
header() = default;
/// Identifies a receiver by name rather than ID.
static const uint8_t named_receiver_flag = 0x01;
/// Queries whether this header has the given flag.
inline bool has(uint8_t flag) const {
return (flags & flag) != 0;
}
}; };
/// @relates header /// @relates header
template <class Processor> template <class Processor>
void serialize(Processor& proc, header& hdr, const unsigned int) { void serialize(Processor& proc, header& hdr, const unsigned int) {
uint8_t pad = 0;
proc & hdr.operation;
proc & pad;
proc & pad;
proc & hdr.flags;
proc & hdr.payload_len;
proc & hdr.operation_data;
proc & hdr.source_node; proc & hdr.source_node;
proc & hdr.dest_node; proc & hdr.dest_node;
proc & hdr.source_actor; proc & hdr.source_actor;
proc & hdr.dest_actor; proc & hdr.dest_actor;
proc & hdr.payload_len;
proc & hdr.operation;
proc & hdr.operation_data;
} }
/// @relates header /// @relates header
......
...@@ -68,10 +68,15 @@ public: ...@@ -68,10 +68,15 @@ public:
virtual void kill_proxy(const node_id& nid, actor_id aid, virtual void kill_proxy(const node_id& nid, actor_id aid,
const error& rsn) = 0; const error& rsn) = 0;
/// Called whenever a `dispatch_message` arrived for a local actor. /// Called for each `dispatch_message` without `named_receiver_flag`.
virtual void deliver(const node_id& source_node, actor_id source_actor, virtual void deliver(const node_id& source_node, actor_id source_actor,
const node_id& dest_node, actor_id dest_actor, actor_id dest_actor, message_id mid,
message_id mid, std::vector<strong_actor_ptr>& forwarding_stack,
message& msg) = 0;
/// Called for each `dispatch_message` with `named_receiver_flag`.
virtual void deliver(const node_id& source_node, actor_id source_actor,
atom_value dest_actor, message_id mid,
std::vector<strong_actor_ptr>& forwarding_stack, std::vector<strong_actor_ptr>& forwarding_stack,
message& msg) = 0; message& msg) = 0;
...@@ -175,19 +180,6 @@ public: ...@@ -175,19 +180,6 @@ public:
return published_actors_; return published_actors_;
} }
/// Writes a header (build from the arguments)
/// followed by its payload to `storage`.
void write(execution_unit* ctx,
buffer_type& storage,
message_type operation,
uint32_t* payload_len,
uint64_t operation_data,
const node_id& source_node,
const node_id& dest_node,
actor_id source_actor,
actor_id dest_actor,
payload_writer* writer = nullptr);
/// Writes a header followed by its payload to `storage`. /// Writes a header followed by its payload to `storage`.
void write(execution_unit* ctx, buffer_type& storage, header& hdr, void write(execution_unit* ctx, buffer_type& storage, header& hdr,
payload_writer* writer = nullptr); payload_writer* writer = nullptr);
...@@ -203,11 +195,13 @@ public: ...@@ -203,11 +195,13 @@ public:
void write_client_handshake(execution_unit* ctx, void write_client_handshake(execution_unit* ctx,
buffer_type& buf, const node_id& remote_side); buffer_type& buf, const node_id& remote_side);
/// Writes a `kill_proxy_instance` to `buf`. /// Writes an `announce_proxy` to `buf`.
void write_kill_proxy_instance(execution_unit* ctx, void write_announce_proxy(execution_unit* ctx, buffer_type& buf,
buffer_type& buf, const node_id& dest_node, actor_id aid);
const node_id& dest_node,
actor_id aid, /// Writes a `kill_proxy` to `buf`.
void write_kill_proxy(execution_unit* ctx, buffer_type& buf,
const node_id& dest_node, actor_id aid,
const error& fail_state); const error& fail_state);
/// Writes a `heartbeat` to `buf`. /// Writes a `heartbeat` to `buf`.
......
...@@ -31,7 +31,7 @@ namespace basp { ...@@ -31,7 +31,7 @@ namespace basp {
/// Describes the first header field of a BASP message and determines the /// Describes the first header field of a BASP message and determines the
/// interpretation of the other header fields. /// interpretation of the other header fields.
enum class message_type : uint32_t { enum class message_type : uint8_t {
/// Send from server, i.e., the node with a published actor, to client, /// Send from server, i.e., the node with a published actor, to client,
/// i.e., node that initiates a new connection using remote_actor(). /// i.e., node that initiates a new connection using remote_actor().
/// ///
...@@ -56,15 +56,16 @@ enum class message_type : uint32_t { ...@@ -56,15 +56,16 @@ enum class message_type : uint32_t {
/// message on termination. /// message on termination.
/// ///
/// ![](announce_proxy_instance.png) /// ![](announce_proxy_instance.png)
announce_proxy_instance = 0x03, announce_proxy = 0x03,
/// Informs the receiving node that it has a proxy for an actor /// Informs the receiving node that it has a proxy for an actor
/// that has been terminated. /// that has been terminated.
/// ///
/// ![](kill_proxy_instance.png) /// ![](kill_proxy_instance.png)
kill_proxy_instance = 0x04, kill_proxy = 0x04,
/// Send to remote node which has direct connection. /// Used to generate periodic traffic between two nodes
/// in order to detect disconnects.
/// ///
/// ![](heartbeat.png) /// ![](heartbeat.png)
heartbeat = 0x05, heartbeat = 0x05,
......
...@@ -29,7 +29,7 @@ namespace basp { ...@@ -29,7 +29,7 @@ namespace basp {
/// The current BASP version. Different BASP versions will not /// The current BASP version. Different BASP versions will not
/// be able to exchange messages. /// be able to exchange messages.
constexpr uint64_t version = 1; constexpr uint64_t version = 2;
/// @} /// @}
......
...@@ -67,9 +67,18 @@ struct basp_broker_state : proxy_registry::backend, basp::instance::callee { ...@@ -67,9 +67,18 @@ struct basp_broker_state : proxy_registry::backend, basp::instance::callee {
// inherited from basp::instance::listener // inherited from basp::instance::listener
void deliver(const node_id& source_node, actor_id source_actor, void deliver(const node_id& source_node, actor_id source_actor,
const node_id& dest_node, actor_id dest_actor, actor_id dest_actor, message_id mid,
message_id mid, std::vector<strong_actor_ptr>& stages, std::vector<strong_actor_ptr>& stages, message& msg) override;
message& msg) override;
// inherited from basp::instance::listener
void deliver(const node_id& source_node, actor_id source_actor,
atom_value dest_actor, message_id mid,
std::vector<strong_actor_ptr>& stages, message& msg) override;
// called from both overriden functions
void deliver(const node_id& source_node, actor_id source_actor,
strong_actor_ptr dest, message_id mid,
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);
......
...@@ -293,15 +293,14 @@ void asio_multiplexer::exec_later(resumable* rptr) { ...@@ -293,15 +293,14 @@ void asio_multiplexer::exec_later(resumable* rptr) {
switch (rptr->subtype()) { switch (rptr->subtype()) {
case resumable::io_actor: case resumable::io_actor:
case resumable::function_object: { case resumable::function_object: {
intrusive_ptr<resumable> ptr{rptr}; intrusive_ptr<resumable> ptr{rptr, false};
service().post([=]() { service().post([=]() mutable {
switch (ptr->resume(this, max_throughput())) { switch (ptr->resume(this, max_throughput())) {
case resumable::resume_later: case resumable::resume_later:
exec_later(ptr.get()); exec_later(ptr.release());
break; break;
case resumable::done: case resumable::done:
case resumable::awaiting_message: case resumable::awaiting_message:
intrusive_ptr_release(ptr.get());
break; break;
default: default:
; // ignored ; // ignored
......
...@@ -104,11 +104,8 @@ strong_actor_ptr basp_broker_state::make_proxy(node_id nid, actor_id aid) { ...@@ -104,11 +104,8 @@ strong_actor_ptr basp_broker_state::make_proxy(node_id nid, actor_id aid) {
"write announce_proxy_instance:" "write announce_proxy_instance:"
<< CAF_ARG(nid) << CAF_ARG(aid)); << CAF_ARG(nid) << CAF_ARG(aid));
// tell remote side we are monitoring this actor now // tell remote side we are monitoring this actor now
instance.write(self->context(), instance.write_announce_proxy(self->context(),
self->wr_buf(this_context->hdl), self->wr_buf(this_context->hdl), nid, aid);
basp::message_type::announce_proxy_instance, nullptr, 0,
this_node(), nid,
invalid_actor_id, aid);
instance.tbl().flush(*path); instance.tbl().flush(*path);
mm->notify<hook::new_remote_actor>(res); mm->notify<hook::new_remote_actor>(res);
return res; return res;
...@@ -177,7 +174,7 @@ void basp_broker_state::proxy_announced(const node_id& nid, actor_id aid) { ...@@ -177,7 +174,7 @@ void basp_broker_state::proxy_announced(const node_id& nid, actor_id aid) {
<< CAF_ARG(nid)); << CAF_ARG(nid));
return; return;
} }
instance.write_kill_proxy_instance(self->context(), path->wr_buf, instance.write_kill_proxy(self->context(), path->wr_buf,
nid, aid, rsn); nid, aid, rsn);
instance.tbl().flush(*path); instance.tbl().flush(*path);
}; };
...@@ -208,43 +205,39 @@ void basp_broker_state::kill_proxy(const node_id& nid, actor_id aid, ...@@ -208,43 +205,39 @@ void basp_broker_state::kill_proxy(const node_id& nid, actor_id aid,
proxies().erase(nid, aid, rsn); proxies().erase(nid, aid, rsn);
} }
void basp_broker_state::deliver(const node_id& src_nid, void basp_broker_state::deliver(const node_id& src_nid, actor_id src_aid,
actor_id src_aid, actor_id dest_aid, message_id mid,
const node_id& dest_nid,
actor_id dest_aid,
message_id mid,
std::vector<strong_actor_ptr>& stages, std::vector<strong_actor_ptr>& stages,
message& msg) { message& msg) {
CAF_LOG_TRACE(CAF_ARG(src_nid) CAF_LOG_TRACE(CAF_ARG(src_nid) << CAF_ARG(src_aid)
<< CAF_ARG(src_aid) << CAF_ARG(dest_nid)
<< CAF_ARG(dest_aid) << CAF_ARG(msg) << CAF_ARG(mid)); << CAF_ARG(dest_aid) << CAF_ARG(msg) << CAF_ARG(mid));
strong_actor_ptr src; deliver(src_nid, src_aid, system().registry().get(dest_aid),
if (src_nid == this_node()) mid, stages, msg);
src = system().registry().get(src_aid); }
else
src = proxies().get_or_put(src_nid, src_aid); void basp_broker_state::deliver(const node_id& src_nid, actor_id src_aid,
strong_actor_ptr dest; atom_value dest_name, message_id mid,
auto rsn = exit_reason::remote_link_unreachable; std::vector<strong_actor_ptr>& stages,
if (dest_nid != this_node()) { message& msg) {
dest = proxies().get_or_put(dest_nid, dest_aid); CAF_LOG_TRACE(CAF_ARG(src_nid) << CAF_ARG(src_aid)
} else { << CAF_ARG(dest_name) << CAF_ARG(msg) << CAF_ARG(mid));
// TODO: replace hack with clean solution deliver(src_nid, src_aid, system().registry().get(dest_name),
if (dest_aid == std::numeric_limits<actor_id>::max()) { mid, stages, msg);
// this hack allows CAF to talk to older CAF versions; CAF <= 0.14 will }
// discard this message silently as the receiver is not found, while
// CAF >= 0.14.1 will use the operation data to identify named actors void basp_broker_state::deliver(const node_id& src_nid, actor_id src_aid,
auto dest_name = static_cast<atom_value>(mid.integer_value()); strong_actor_ptr dest, message_id mid,
CAF_LOG_DEBUG(CAF_ARG(dest_name)); std::vector<strong_actor_ptr>& stages,
mid = message_id::make(); // override this since the message is async message& msg) {
dest = system().registry().get(dest_name); CAF_LOG_TRACE(CAF_ARG(src_nid) << CAF_ARG(src_aid) << CAF_ARG(dest)
} else { << CAF_ARG(msg) << CAF_ARG(mid));
dest = system().registry().get(dest_aid); auto src = src_nid == this_node() ? system().registry().get(src_aid)
} : proxies().get_or_put(src_nid, src_aid);
}
if (! dest) { if (! dest) {
auto rsn = exit_reason::remote_link_unreachable;
CAF_LOG_INFO("cannot deliver message, destination not found"); CAF_LOG_INFO("cannot deliver message, destination not found");
self->parent().notify<hook::invalid_message_received>(src_nid, src, self->parent().notify<hook::invalid_message_received>(src_nid, src,
dest_aid, mid, msg); 0, mid, msg);
if (mid.valid() && src) { if (mid.valid() && src) {
detail::sync_request_bouncer srb{rsn}; detail::sync_request_bouncer srb{rsn};
srb(src, mid); srb(src, mid);
...@@ -303,24 +296,30 @@ void basp_broker_state::learned_new_node(const node_id& nid) { ...@@ -303,24 +296,30 @@ void basp_broker_state::learned_new_node(const node_id& nid) {
using namespace detail; using namespace detail;
system().registry().put(tmp.id(), actor_cast<strong_actor_ptr>(tmp)); system().registry().put(tmp.id(), actor_cast<strong_actor_ptr>(tmp));
auto writer = make_callback([](serializer& sink) { auto writer = make_callback([](serializer& sink) {
auto name = atom("SpawnServ");
std::vector<actor_id> stages; std::vector<actor_id> stages;
auto msg = make_message(sys_atom::value, get_atom::value, "info"); auto msg = make_message(sys_atom::value, get_atom::value, "info");
sink << stages << msg; sink << name << stages << msg;
}); });
auto path = instance.tbl().lookup(nid); auto path = instance.tbl().lookup(nid);
if (! path) { if (! path) {
CAF_LOG_ERROR("learned_new_node called, but no route to nid"); CAF_LOG_ERROR("learned_new_node called, but no route to nid");
return; return;
} }
// send message to SpawnServ of remote node
basp::header hdr{basp::message_type::dispatch_message,
basp::header::named_receiver_flag,
0, 0, this_node(), nid, tmp.id(), invalid_actor_id};
// writing std::numeric_limits<actor_id>::max() is a hack to get // writing std::numeric_limits<actor_id>::max() is a hack to get
// this send-to-named-actor feature working with older CAF releases // this send-to-named-actor feature working with older CAF releases
instance.write(self->context(), instance.write(self->context(), path->wr_buf, hdr, &writer);
path->wr_buf, /*
basp::message_type::dispatch_message, basp::message_type::dispatch_message,
nullptr, static_cast<uint64_t>(atom("SpawnServ")), nullptr, static_cast<uint64_t>(atom("SpawnServ")),
this_node(), nid, this_node(), nid,
tmp.id(), std::numeric_limits<actor_id>::max(), tmp.id(), std::numeric_limits<actor_id>::max(),
&writer); &writer);
*/
instance.flush(*path); instance.flush(*path);
} }
...@@ -400,19 +399,15 @@ void basp_broker_state::learned_new_node_indirectly(const node_id& nid) { ...@@ -400,19 +399,15 @@ void basp_broker_state::learned_new_node_indirectly(const node_id& nid) {
auto tmp = system().spawn<detached + hidden>(connection_helper, self); auto tmp = system().spawn<detached + hidden>(connection_helper, self);
system().registry().put(tmp.id(), actor_cast<strong_actor_ptr>(tmp)); system().registry().put(tmp.id(), actor_cast<strong_actor_ptr>(tmp));
auto writer = make_callback([](serializer& sink) { auto writer = make_callback([](serializer& sink) {
auto name = atom("ConfigServ");
std::vector<actor_id> stages; std::vector<actor_id> stages;
auto msg = make_message(get_atom::value, "basp.default-connectivity"); auto msg = make_message(get_atom::value, "basp.default-connectivity");
sink << stages << msg; sink << name << stages << msg;
}); });
// writing std::numeric_limits<actor_id>::max() is a hack to get basp::header hdr{basp::message_type::dispatch_message,
// this send-to-named-actor feature working with older CAF releases basp::header::named_receiver_flag,
instance.write(self->context(), 0, 0, this_node(), nid, tmp.id(), invalid_actor_id};
path->wr_buf, instance.write(self->context(), path->wr_buf, hdr, &writer);
basp::message_type::dispatch_message,
nullptr, static_cast<uint64_t>(atom("ConfigServ")),
this_node(), nid,
tmp.id(), std::numeric_limits<actor_id>::max(),
&writer);
instance.flush(*path); instance.flush(*path);
} }
...@@ -424,8 +419,8 @@ void basp_broker_state::set_context(connection_handle hdl) { ...@@ -424,8 +419,8 @@ void basp_broker_state::set_context(connection_handle hdl) {
i = ctx.emplace(hdl, i = ctx.emplace(hdl,
connection_context{ connection_context{
basp::await_header, basp::await_header,
basp::header{basp::message_type::server_handshake, 0, 0, basp::header{basp::message_type::server_handshake, 0,
invalid_node_id, invalid_node_id, 0, 0, invalid_node_id, invalid_node_id,
invalid_actor_id, invalid_actor_id}, invalid_actor_id, invalid_actor_id},
hdl, hdl,
invalid_node_id, invalid_node_id,
...@@ -524,23 +519,18 @@ behavior basp_broker::make_behavior() { ...@@ -524,23 +519,18 @@ behavior basp_broker::make_behavior() {
system().registry().put(sender->id(), sender); system().registry().put(sender->id(), sender);
auto writer = make_callback([&](serializer& sink) { auto writer = make_callback([&](serializer& sink) {
std::vector<actor_addr> stages; std::vector<actor_addr> stages;
sink << stages << msg; sink << receiver_name << stages << msg;
}); });
auto path = this->state.instance.tbl().lookup(receiving_node); auto path = this->state.instance.tbl().lookup(receiving_node);
if (! path) { if (! path) {
CAF_LOG_ERROR("no route to receiving node"); CAF_LOG_ERROR("no route to receiving node");
return sec::no_route_to_receiving_node; return sec::no_route_to_receiving_node;
} }
// writing std::numeric_limits<actor_id>::max() is a hack to get basp::header hdr{basp::message_type::dispatch_message,
// this send-to-named-actor feature working with older CAF releases basp::header::named_receiver_flag,
this->state.instance.write(context(), 0, 0, state.this_node(), receiving_node,
path->wr_buf, sender->id(), invalid_actor_id};
basp::message_type::dispatch_message, state.instance.write(context(), path->wr_buf, hdr, &writer);
nullptr, static_cast<uint64_t>(receiver_name),
state.this_node(), receiving_node,
sender->id(),
std::numeric_limits<actor_id>::max(),
&writer);
state.instance.flush(*path); state.instance.flush(*path);
return unit; return unit;
}, },
......
...@@ -25,10 +25,20 @@ namespace caf { ...@@ -25,10 +25,20 @@ namespace caf {
namespace io { namespace io {
namespace basp { namespace basp {
const uint8_t header::named_receiver_flag;
std::string to_bin(uint8_t x) {
std::string res;
for (auto offset = 7; offset > 0; --offset)
res += std::to_string((x >> offset) & 0x01);
return res;
}
std::string to_string(const header &hdr) { std::string to_string(const header &hdr) {
std::ostringstream oss; std::ostringstream oss;
oss << "{" oss << "{"
<< to_string(hdr.operation) << ", " << to_string(hdr.operation) << ", "
<< to_bin(hdr.flags) << ", "
<< hdr.payload_len << ", " << hdr.payload_len << ", "
<< hdr.operation_data << ", " << hdr.operation_data << ", "
<< to_string(hdr.source_node) << ", " << to_string(hdr.source_node) << ", "
...@@ -41,6 +51,7 @@ std::string to_string(const header &hdr) { ...@@ -41,6 +51,7 @@ std::string to_string(const header &hdr) {
bool operator==(const header& lhs, const header& rhs) { bool operator==(const header& lhs, const header& rhs) {
return lhs.operation == rhs.operation return lhs.operation == rhs.operation
&& lhs.flags == rhs.flags
&& lhs.payload_len == rhs.payload_len && lhs.payload_len == rhs.payload_len
&& lhs.operation_data == rhs.operation_data && lhs.operation_data == rhs.operation_data
&& lhs.source_node == rhs.source_node && lhs.source_node == rhs.source_node
...@@ -79,7 +90,7 @@ bool client_handshake_valid(const header& hdr) { ...@@ -79,7 +90,7 @@ bool client_handshake_valid(const header& hdr) {
bool dispatch_message_valid(const header& hdr) { bool dispatch_message_valid(const header& hdr) {
return valid(hdr.dest_node) return valid(hdr.dest_node)
&& ! zero(hdr.dest_actor) && (! zero(hdr.dest_actor) || hdr.has(header::named_receiver_flag))
&& ! zero(hdr.payload_len); && ! zero(hdr.payload_len);
} }
...@@ -125,9 +136,9 @@ bool valid(const header& hdr) { ...@@ -125,9 +136,9 @@ bool valid(const header& hdr) {
return client_handshake_valid(hdr); return client_handshake_valid(hdr);
case message_type::dispatch_message: case message_type::dispatch_message:
return dispatch_message_valid(hdr); return dispatch_message_valid(hdr);
case message_type::announce_proxy_instance: case message_type::announce_proxy:
return announce_proxy_instance_valid(hdr); return announce_proxy_instance_valid(hdr);
case message_type::kill_proxy_instance: case message_type::kill_proxy:
return kill_proxy_instance_valid(hdr); return kill_proxy_instance_valid(hdr);
case message_type::heartbeat: case message_type::heartbeat:
return heartbeat_valid(hdr); return heartbeat_valid(hdr);
......
...@@ -173,20 +173,27 @@ connection_state instance::handle(execution_unit* ctx, ...@@ -173,20 +173,27 @@ connection_state instance::handle(execution_unit* ctx,
&& tbl_.add_indirect(last_hop, hdr.source_node)) && tbl_.add_indirect(last_hop, hdr.source_node))
callee_.learned_new_node_indirectly(hdr.source_node); callee_.learned_new_node_indirectly(hdr.source_node);
binary_deserializer bd{ctx, *payload}; binary_deserializer bd{ctx, *payload};
auto receiver_name = static_cast<atom_value>(0);
std::vector<strong_actor_ptr> forwarding_stack; std::vector<strong_actor_ptr> forwarding_stack;
message msg; message msg;
if (hdr.has(header::named_receiver_flag))
bd >> receiver_name;
bd >> forwarding_stack >> msg; bd >> forwarding_stack >> msg;
CAF_LOG_DEBUG(CAF_ARG(forwarding_stack) << CAF_ARG(msg)); CAF_LOG_DEBUG(CAF_ARG(forwarding_stack) << CAF_ARG(msg));
callee_.deliver(hdr.source_node, hdr.source_actor, if (hdr.has(header::named_receiver_flag))
hdr.dest_node, hdr.dest_actor, callee_.deliver(hdr.source_node, hdr.source_actor, receiver_name,
message_id::from_integer_value(hdr.operation_data),
forwarding_stack, msg);
else
callee_.deliver(hdr.source_node, hdr.source_actor, hdr.dest_actor,
message_id::from_integer_value(hdr.operation_data), message_id::from_integer_value(hdr.operation_data),
forwarding_stack, msg); forwarding_stack, msg);
break; break;
} }
case message_type::announce_proxy_instance: case message_type::announce_proxy:
callee_.proxy_announced(hdr.source_node, hdr.dest_actor); callee_.proxy_announced(hdr.source_node, hdr.dest_actor);
break; break;
case message_type::kill_proxy_instance: { case message_type::kill_proxy: {
if (! payload_valid()) if (! payload_valid())
return err(); return err();
binary_deserializer bd{ctx, *payload}; binary_deserializer bd{ctx, *payload};
...@@ -311,7 +318,7 @@ bool instance::dispatch(execution_unit* ctx, const strong_actor_ptr& sender, ...@@ -311,7 +318,7 @@ bool instance::dispatch(execution_unit* ctx, const strong_actor_ptr& sender,
auto writer = make_callback([&](serializer& sink) { auto writer = make_callback([&](serializer& sink) {
sink << forwarding_stack << msg; sink << forwarding_stack << msg;
}); });
header hdr{message_type::dispatch_message, 0, mid.integer_value(), header hdr{message_type::dispatch_message, 0, 0, mid.integer_value(),
sender ? sender->node() : this_node(), receiver->node(), sender ? sender->node() : this_node(), receiver->node(),
sender ? sender->id() : invalid_actor_id, receiver->id()}; sender ? sender->id() : invalid_actor_id, receiver->id()};
write(ctx, path->wr_buf, hdr, &writer); write(ctx, path->wr_buf, hdr, &writer);
...@@ -320,65 +327,30 @@ bool instance::dispatch(execution_unit* ctx, const strong_actor_ptr& sender, ...@@ -320,65 +327,30 @@ bool instance::dispatch(execution_unit* ctx, const strong_actor_ptr& sender,
return true; return true;
} }
void instance::write(execution_unit* ctx, void instance::write(execution_unit* ctx, buffer_type& buf,
buffer_type& buf, header& hdr, payload_writer* pw) {
message_type operation, CAF_LOG_TRACE(CAF_ARG(hdr));
uint32_t* payload_len, try {
uint64_t operation_data, if (pw) {
const node_id& source_node, auto pos = buf.size();
const node_id& dest_node, // write payload first (skip first 72 bytes and write header later)
actor_id source_actor,
actor_id dest_actor,
payload_writer* pw) {
CAF_LOG_TRACE(CAF_ARG(operation) << CAF_ARG(operation_data)
<< CAF_ARG(source_node) << CAF_ARG(dest_node)
<< CAF_ARG(source_actor) << CAF_ARG(dest_actor));
if (! pw) {
CAF_LOG_DEBUG("send message without payload");
uint32_t zero = 0;
binary_serializer bs{ctx, buf};
bs << source_node
<< dest_node
<< source_actor
<< dest_actor
<< zero
<< operation
<< operation_data;
return;
}
// reserve space in the buffer to write the payload later on
auto wr_pos = buf.size();
char placeholder[basp::header_size]; char placeholder[basp::header_size];
buf.insert(buf.end(), std::begin(placeholder), std::end(placeholder)); buf.insert(buf.end(), std::begin(placeholder), std::end(placeholder));
auto pl_pos = buf.size();
try { // lifetime scope of first serializer (write payload)
binary_serializer bs{ctx, buf}; binary_serializer bs{ctx, buf};
(*pw)(bs); (*pw)(bs);
auto plen = buf.size() - pos - basp::header_size;
CAF_ASSERT(plen <= std::numeric_limits<uint32_t>::max());
hdr.payload_len = static_cast<uint32_t>(plen);
stream_serializer<charbuf> out{ctx, buf.data() + pos, basp::header_size};
out << hdr;
} else {
binary_serializer bs{ctx, buf};
bs << hdr;
}
} }
catch (std::exception& e) { catch (std::exception& e) {
printf("EXCEPTION: %s\n", e.what());
CAF_LOG_ERROR(CAF_ARG(e.what())); CAF_LOG_ERROR(CAF_ARG(e.what()));
} }
// write broker message to the reserved space
stream_serializer<charbuf> bs2{ctx, buf.data() + wr_pos, pl_pos - wr_pos};
auto plen = static_cast<uint32_t>(buf.size() - pl_pos);
bs2 << source_node
<< dest_node
<< source_actor
<< dest_actor
<< plen
<< operation
<< operation_data;
CAF_LOG_DEBUG("wrote payload" << CAF_ARG(plen));
if (payload_len)
*payload_len = plen;
}
void instance::write(execution_unit* ctx, buffer_type& buf,
header& hdr, payload_writer* pw) {
CAF_LOG_TRACE(CAF_ARG(hdr));
write(ctx, buf, hdr.operation, &hdr.payload_len, hdr.operation_data,
hdr.source_node, hdr.dest_node, hdr.source_actor, hdr.dest_actor, pw);
} }
void instance::write_server_handshake(execution_unit* ctx, void instance::write_server_handshake(execution_unit* ctx,
...@@ -399,7 +371,7 @@ void instance::write_server_handshake(execution_unit* ctx, ...@@ -399,7 +371,7 @@ void instance::write_server_handshake(execution_unit* ctx,
sink << i << pa->second; sink << i << pa->second;
} }
}); });
header hdr{message_type::server_handshake, 0, version, header hdr{message_type::server_handshake, 0, 0, version,
this_node_, invalid_node_id, this_node_, invalid_node_id,
pa && pa->first ? pa->first->id() : invalid_actor_id, pa && pa->first ? pa->first->id() : invalid_actor_id,
invalid_actor_id}; invalid_actor_id};
...@@ -410,20 +382,27 @@ void instance::write_client_handshake(execution_unit* ctx, ...@@ -410,20 +382,27 @@ void instance::write_client_handshake(execution_unit* ctx,
buffer_type& buf, buffer_type& buf,
const node_id& remote_side) { const node_id& remote_side) {
CAF_LOG_TRACE(CAF_ARG(remote_side)); CAF_LOG_TRACE(CAF_ARG(remote_side));
write(ctx, buf, message_type::client_handshake, nullptr, 0, header hdr{message_type::client_handshake, 0, 0, 0,
this_node_, remote_side, invalid_actor_id, invalid_actor_id); this_node_, remote_side, invalid_actor_id, invalid_actor_id};
write(ctx, buf, hdr);
} }
void instance::write_kill_proxy_instance(execution_unit* ctx, void instance::write_announce_proxy(execution_unit* ctx, buffer_type& buf,
buffer_type& buf, const node_id& dest_node, actor_id aid) {
const node_id& dest_node, CAF_LOG_TRACE(CAF_ARG(dest_node) << CAF_ARG(aid));
actor_id aid, header hdr{message_type::announce_proxy, 0, 0, 0,
this_node_, dest_node, invalid_actor_id, aid};
write(ctx, buf, hdr);
}
void instance::write_kill_proxy(execution_unit* ctx, buffer_type& buf,
const node_id& dest_node, actor_id aid,
const error& rsn) { const error& rsn) {
CAF_LOG_TRACE(CAF_ARG(dest_node) << CAF_ARG(aid) << CAF_ARG(rsn)); CAF_LOG_TRACE(CAF_ARG(dest_node) << CAF_ARG(aid) << CAF_ARG(rsn));
auto writer = make_callback([&](serializer& sink) { auto writer = make_callback([&](serializer& sink) {
sink << rsn; sink << rsn;
}); });
header hdr{message_type::kill_proxy_instance, 0, 0, header hdr{message_type::kill_proxy, 0, 0, 0,
this_node_, dest_node, aid, invalid_actor_id}; this_node_, dest_node, aid, invalid_actor_id};
write(ctx, buf, hdr, &writer); write(ctx, buf, hdr, &writer);
} }
...@@ -432,8 +411,9 @@ void instance::write_heartbeat(execution_unit* ctx, ...@@ -432,8 +411,9 @@ void instance::write_heartbeat(execution_unit* ctx,
buffer_type& buf, buffer_type& buf,
const node_id& remote_side) { const node_id& remote_side) {
CAF_LOG_TRACE(CAF_ARG(remote_side)); CAF_LOG_TRACE(CAF_ARG(remote_side));
write(ctx, buf, message_type::heartbeat, nullptr, 0, header hdr{message_type::heartbeat, 0, 0, 0,
this_node_, remote_side, invalid_actor_id, invalid_actor_id); this_node_, remote_side, invalid_actor_id, invalid_actor_id};
write(ctx, buf, hdr);
} }
} // namespace basp } // namespace basp
......
...@@ -31,9 +31,9 @@ std::string to_string(message_type x) { ...@@ -31,9 +31,9 @@ std::string to_string(message_type x) {
return "client_handshake"; return "client_handshake";
case message_type::dispatch_message: case message_type::dispatch_message:
return "dispatch_message"; return "dispatch_message";
case message_type::announce_proxy_instance: case message_type::announce_proxy:
return "announce_proxy_instance"; return "announce_proxy_instance";
case message_type::kill_proxy_instance: case message_type::kill_proxy:
return "kill_proxy_instance"; return "kill_proxy_instance";
case message_type::heartbeat: case message_type::heartbeat:
return "heartbeat"; return "heartbeat";
......
...@@ -43,6 +43,17 @@ struct anything { }; ...@@ -43,6 +43,17 @@ struct anything { };
anything any_vals; anything any_vals;
template <class T>
using maybe = caf::variant<anything, T>;
constexpr uint8_t no_flags = 0;
constexpr uint32_t no_payload = 0;
constexpr uint64_t no_operation_data = 0;
constexpr auto basp_atom = caf::atom("BASP");
constexpr auto spawn_serv_atom = caf::atom("SpawnServ");
constexpr auto config_serv_atom = caf::atom("ConfigServ");
} // namespace <anonymous> } // namespace <anonymous>
namespace std { namespace std {
...@@ -52,7 +63,7 @@ ostream& operator<<(ostream& out, const caf::io::basp::message_type& x) { ...@@ -52,7 +63,7 @@ ostream& operator<<(ostream& out, const caf::io::basp::message_type& x) {
} }
template <class T> template <class T>
ostream& operator<<(ostream& out, const caf::variant<anything, T>& x) { ostream& operator<<(ostream& out, const maybe<T>& x) {
using std::to_string; using std::to_string;
using caf::to_string; using caf::to_string;
using caf::io::basp::to_string; using caf::io::basp::to_string;
...@@ -65,18 +76,18 @@ ostream& operator<<(ostream& out, const caf::variant<anything, T>& x) { ...@@ -65,18 +76,18 @@ ostream& operator<<(ostream& out, const caf::variant<anything, T>& x) {
namespace caf { namespace caf {
template <class T> template <class T, class U>
bool operator==(const variant<anything, T>& x, const T& y) { bool operator==(const maybe<T>& x, const U& y) {
return get<anything>(&x) != nullptr || get<T>(x) == y; return get<anything>(&x) != nullptr || get<T>(x) == y;
} }
template <class T> template <class T, class U>
bool operator==(const T& x, const variant<anything, T>& y) { bool operator==(const T& x, const maybe<U>& y) {
return (y == x); return (y == x);
} }
template <class T> template <class T>
std::string to_string(const variant<anything, T>& x) { std::string to_string(const maybe<T>& x) {
return ! get<anything>(&x) ? std::string{"*"} : deep_to_string(get<T>(x)); return ! get<anything>(&x) ? std::string{"*"} : deep_to_string(get<T>(x));
} }
...@@ -98,7 +109,7 @@ string hexstr(const buffer& buf) { ...@@ -98,7 +109,7 @@ string hexstr(const buffer& buf) {
oss.fill('0'); oss.fill('0');
for (auto& c : buf) { for (auto& c : buf) {
oss.width(2); oss.width(2);
oss << int{c}; oss << int{static_cast<uint8_t>(c)};
} }
return oss.str(); return oss.str();
} }
...@@ -113,7 +124,7 @@ public: ...@@ -113,7 +124,7 @@ public:
mpx_ = dynamic_cast<network::test_multiplexer*>(&mm.backend()); mpx_ = dynamic_cast<network::test_multiplexer*>(&mm.backend());
CAF_REQUIRE(mpx_ != nullptr); CAF_REQUIRE(mpx_ != nullptr);
CAF_REQUIRE(&system == &mpx_->system()); CAF_REQUIRE(&system == &mpx_->system());
auto hdl = mm.named_broker<basp_broker>(atom("BASP")); auto hdl = mm.named_broker<basp_broker>(basp_atom);
aut_ = static_cast<basp_broker*>(actor_cast<abstract_actor*>(hdl)); aut_ = static_cast<basp_broker*>(actor_cast<abstract_actor*>(hdl));
this_node_ = system.node(); this_node_ = system.node();
CAF_MESSAGE("this node: " << to_string(this_node_)); CAF_MESSAGE("this node: " << to_string(this_node_));
...@@ -278,28 +289,30 @@ public: ...@@ -278,28 +289,30 @@ public:
// technically, the server handshake arrives // technically, the server handshake arrives
// before we send the client handshake // before we send the client handshake
auto m = mock(hdl, auto m = mock(hdl,
{basp::message_type::client_handshake, 0, 0, {basp::message_type::client_handshake, 0, 0, 0,
remote_node(i), this_node(), remote_node(i), this_node(),
invalid_actor_id, invalid_actor_id}); invalid_actor_id, invalid_actor_id});
if (published_actor_id != invalid_actor_id) if (published_actor_id != invalid_actor_id)
m.expect(hdl, m.expect(hdl,
basp::message_type::server_handshake, any_vals, basp::version, basp::message_type::server_handshake, no_flags,
this_node(), node_id{invalid_node_id}, any_vals, basp::version, this_node(), node_id{invalid_node_id},
published_actor_id, invalid_actor_id, published_actor_id, invalid_actor_id,
published_actor_id, published_actor_id,
published_actor_ifs); published_actor_ifs);
else else
m.expect(hdl, m.expect(hdl,
basp::message_type::server_handshake, any_vals, basp::version, basp::message_type::server_handshake, no_flags, any_vals,
this_node(), node_id{invalid_node_id}, basp::version, this_node(), node_id{invalid_node_id},
invalid_actor_id, invalid_actor_id); invalid_actor_id, invalid_actor_id);
// upon receiving our client handshake, BASP will check // upon receiving our client handshake, BASP will check
// whether there is a SpawnServ actor on this node // whether there is a SpawnServ actor on this node
m.expect(hdl, m.expect(hdl,
basp::message_type::dispatch_message, any_vals, basp::message_type::dispatch_message,
static_cast<uint64_t>(atom("SpawnServ")), basp::header::named_receiver_flag, any_vals,
no_operation_data,
this_node(), remote_node(i), this_node(), remote_node(i),
any_vals, std::numeric_limits<actor_id>::max(), any_vals, invalid_actor_id,
spawn_serv_atom,
std::vector<actor_addr>{}, std::vector<actor_addr>{},
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
...@@ -355,15 +368,16 @@ public: ...@@ -355,15 +368,16 @@ public:
template <class... Ts> template <class... Ts>
mock_t& expect(connection_handle hdl, mock_t& expect(connection_handle hdl,
variant<anything, basp::message_type> operation, maybe<basp::message_type> operation,
variant<anything, uint32_t> payload_len, maybe<uint8_t> flags,
variant<anything, uint64_t> operation_data, maybe<uint32_t> payload_len,
variant<anything, node_id> source_node, maybe<uint64_t> operation_data,
variant<anything, node_id> dest_node, maybe<node_id> source_node,
variant<anything, actor_id> source_actor, maybe<node_id> dest_node,
variant<anything, actor_id> dest_actor, maybe<actor_id> source_actor,
maybe<actor_id> dest_actor,
const Ts&... xs) { const Ts&... xs) {
CAF_MESSAGE("expect " << num); CAF_MESSAGE("expect #" << num);
buffer buf; buffer buf;
this_->to_payload(buf, xs...); this_->to_payload(buf, xs...);
buffer& ob = this_->mpx()->output_buffer(hdl); buffer& ob = this_->mpx()->output_buffer(hdl);
...@@ -388,14 +402,16 @@ public: ...@@ -388,14 +402,16 @@ public:
ob.erase(ob.begin(), ob.begin() + basp::header_size); ob.erase(ob.begin(), ob.begin() + basp::header_size);
} }
CAF_CHECK_EQUAL(operation, hdr.operation); CAF_CHECK_EQUAL(operation, hdr.operation);
CAF_CHECK_EQUAL(flags, static_cast<size_t>(hdr.flags));
CAF_CHECK_EQUAL(payload_len, hdr.payload_len); CAF_CHECK_EQUAL(payload_len, hdr.payload_len);
CAF_CHECK_EQUAL(operation_data, hdr.operation_data); CAF_CHECK_EQUAL(operation_data, hdr.operation_data);
CAF_CHECK_EQUAL(source_node, hdr.source_node); CAF_CHECK_EQUAL(source_node, hdr.source_node);
CAF_CHECK_EQUAL(dest_node, hdr.dest_node); CAF_CHECK_EQUAL(dest_node, hdr.dest_node);
CAF_CHECK_EQUAL(source_actor, hdr.source_actor); CAF_CHECK_EQUAL(source_actor, hdr.source_actor);
CAF_CHECK_EQUAL(dest_actor, hdr.dest_actor); CAF_CHECK_EQUAL(dest_actor, hdr.dest_actor);
CAF_REQUIRE(payload.size() == buf.size()); printf("buf.size: %d, payload.size: %d\n", (int) buf.size(), (int) payload.size());
CAF_REQUIRE(hexstr(payload) == hexstr(buf)); CAF_REQUIRE_EQUAL(buf.size(), payload.size());
CAF_REQUIRE_EQUAL(hexstr(buf), hexstr(payload));
++num; ++num;
return *this; return *this;
} }
...@@ -453,7 +469,7 @@ CAF_TEST(empty_server_handshake) { ...@@ -453,7 +469,7 @@ CAF_TEST(empty_server_handshake) {
basp::header hdr; basp::header hdr;
buffer payload; buffer payload;
std::tie(hdr, payload) = from_buf(buf); std::tie(hdr, payload) = from_buf(buf);
basp::header expected{basp::message_type::server_handshake, basp::header expected{basp::message_type::server_handshake, 0,
static_cast<uint32_t>(payload.size()), static_cast<uint32_t>(payload.size()),
basp::version, basp::version,
this_node(), invalid_node_id, this_node(), invalid_node_id,
...@@ -471,8 +487,8 @@ CAF_TEST(non_empty_server_handshake) { ...@@ -471,8 +487,8 @@ CAF_TEST(non_empty_server_handshake) {
{"caf::replies_to<@u16>::with<@u16>"}); {"caf::replies_to<@u16>::with<@u16>"});
instance().write_server_handshake(mpx(), buf, uint16_t{4242}); instance().write_server_handshake(mpx(), buf, uint16_t{4242});
buffer expected_buf; buffer expected_buf;
basp::header expected{basp::message_type::server_handshake, 0, basp::version, basp::header expected{basp::message_type::server_handshake, 0, 0,
this_node(), invalid_node_id, basp::version, this_node(), invalid_node_id,
self()->id(), invalid_actor_id}; self()->id(), invalid_actor_id};
to_buf(expected_buf, expected, nullptr, to_buf(expected_buf, expected, nullptr,
self()->id(), set<string>{"caf::replies_to<@u16>::with<@u16>"}); self()->id(), set<string>{"caf::replies_to<@u16>::with<@u16>"});
...@@ -503,13 +519,13 @@ CAF_TEST(client_handshake_and_dispatch) { ...@@ -503,13 +519,13 @@ CAF_TEST(client_handshake_and_dispatch) {
connect_node(0); connect_node(0);
// send a message via `dispatch` from node 0 // send a message via `dispatch` from node 0
mock(remote_hdl(0), mock(remote_hdl(0),
{basp::message_type::dispatch_message, 0, 0, {basp::message_type::dispatch_message, 0, 0, 0,
remote_node(0), this_node(), pseudo_remote(0)->id(), self()->id()}, remote_node(0), this_node(), pseudo_remote(0)->id(), self()->id()},
std::vector<actor_addr>{}, std::vector<actor_addr>{},
make_message(1, 2, 3)) make_message(1, 2, 3))
.expect(remote_hdl(0), .expect(remote_hdl(0),
basp::message_type::announce_proxy_instance, uint32_t{0}, uint64_t{0}, basp::message_type::announce_proxy, no_flags, no_payload,
this_node(), remote_node(0), no_operation_data, this_node(), remote_node(0),
invalid_actor_id, pseudo_remote(0)->id()); invalid_actor_id, pseudo_remote(0)->id());
// must've created a proxy for our remote actor // must've created a proxy for our remote actor
CAF_REQUIRE(proxies().count_proxies(remote_node(0)) == 1); CAF_REQUIRE(proxies().count_proxies(remote_node(0)) == 1);
...@@ -540,13 +556,13 @@ CAF_TEST(message_forwarding) { ...@@ -540,13 +556,13 @@ CAF_TEST(message_forwarding) {
auto msg = make_message(1, 2, 3); auto msg = make_message(1, 2, 3);
// send a message from node 0 to node 1, forwarded by this node // send a message from node 0 to node 1, forwarded by this node
mock(remote_hdl(0), mock(remote_hdl(0),
{basp::message_type::dispatch_message, 0, 0, {basp::message_type::dispatch_message, 0, 0, 0,
remote_node(0), remote_node(1), remote_node(0), remote_node(1),
invalid_actor_id, pseudo_remote(1)->id()}, invalid_actor_id, pseudo_remote(1)->id()},
msg) msg)
.expect(remote_hdl(1), .expect(remote_hdl(1),
basp::message_type::dispatch_message, any_vals, uint64_t{0}, basp::message_type::dispatch_message, no_flags, any_vals,
remote_node(0), remote_node(1), no_operation_data, remote_node(0), remote_node(1),
invalid_actor_id, pseudo_remote(1)->id(), invalid_actor_id, pseudo_remote(1)->id(),
msg); msg);
} }
...@@ -577,25 +593,26 @@ CAF_TEST(remote_actor_and_send) { ...@@ -577,25 +593,26 @@ CAF_TEST(remote_actor_and_send) {
CAF_MESSAGE("server handshake => client handshake + proxy announcement"); CAF_MESSAGE("server handshake => client handshake + proxy announcement");
auto na = registry()->named_actors(); auto na = registry()->named_actors();
mock(remote_hdl(0), mock(remote_hdl(0),
{basp::message_type::server_handshake, 0, basp::version, {basp::message_type::server_handshake, 0, 0, basp::version,
remote_node(0), invalid_node_id, remote_node(0), invalid_node_id,
pseudo_remote(0)->id(), invalid_actor_id}, pseudo_remote(0)->id(), invalid_actor_id},
pseudo_remote(0)->id(), pseudo_remote(0)->id(),
uint32_t{0}) uint32_t{0})
.expect(remote_hdl(0), .expect(remote_hdl(0),
basp::message_type::client_handshake, uint32_t{0}, uint64_t{0}, basp::message_type::client_handshake, no_flags, no_payload,
this_node(), remote_node(0), no_operation_data, this_node(), remote_node(0),
invalid_actor_id, invalid_actor_id) invalid_actor_id, invalid_actor_id)
.expect(remote_hdl(0), .expect(remote_hdl(0),
basp::message_type::dispatch_message, any_vals, basp::message_type::dispatch_message,
static_cast<uint64_t>(atom("SpawnServ")), basp::header::named_receiver_flag, any_vals,
this_node(), remote_node(0), no_operation_data, this_node(), remote_node(0),
any_vals, std::numeric_limits<actor_id>::max(), any_vals, invalid_actor_id,
spawn_serv_atom,
std::vector<actor_id>{}, std::vector<actor_id>{},
make_message(sys_atom::value, get_atom::value, "info")) make_message(sys_atom::value, get_atom::value, "info"))
.expect(remote_hdl(0), .expect(remote_hdl(0),
basp::message_type::announce_proxy_instance, uint32_t{0}, uint64_t{0}, basp::message_type::announce_proxy, no_flags, no_payload,
this_node(), remote_node(0), no_operation_data, this_node(), remote_node(0),
invalid_actor_id, pseudo_remote(0)->id()); invalid_actor_id, pseudo_remote(0)->id());
CAF_MESSAGE("BASP broker should've send the proxy"); CAF_MESSAGE("BASP broker should've send the proxy");
f.receive( f.receive(
...@@ -620,15 +637,15 @@ CAF_TEST(remote_actor_and_send) { ...@@ -620,15 +637,15 @@ CAF_TEST(remote_actor_and_send) {
// mpx()->exec_runnable(); // process forwarded message in basp_broker // mpx()->exec_runnable(); // process forwarded message in basp_broker
mock() mock()
.expect(remote_hdl(0), .expect(remote_hdl(0),
basp::message_type::dispatch_message, any_vals, uint64_t{0}, basp::message_type::dispatch_message, no_flags, any_vals,
this_node(), remote_node(0), no_operation_data, this_node(), remote_node(0),
invalid_actor_id, pseudo_remote(0)->id(), invalid_actor_id, pseudo_remote(0)->id(),
std::vector<actor_id>{}, std::vector<actor_id>{},
make_message(42)); make_message(42));
auto msg = make_message("hi there!"); auto msg = make_message("hi there!");
CAF_MESSAGE("send message via BASP (from proxy)"); CAF_MESSAGE("send message via BASP (from proxy)");
mock(remote_hdl(0), mock(remote_hdl(0),
{basp::message_type::dispatch_message, 0, 0, {basp::message_type::dispatch_message, 0, 0, 0,
remote_node(0), this_node(), remote_node(0), this_node(),
pseudo_remote(0)->id(), self()->id()}, pseudo_remote(0)->id(), self()->id()},
std::vector<actor_id>{}, std::vector<actor_id>{},
...@@ -655,8 +672,8 @@ CAF_TEST(actor_serialize_and_deserialize) { ...@@ -655,8 +672,8 @@ CAF_TEST(actor_serialize_and_deserialize) {
auto prx = proxies().get_or_put(remote_node(0), pseudo_remote(0)->id()); auto prx = proxies().get_or_put(remote_node(0), pseudo_remote(0)->id());
mock() mock()
.expect(remote_hdl(0), .expect(remote_hdl(0),
basp::message_type::announce_proxy_instance, uint32_t{0}, uint64_t{0}, basp::message_type::announce_proxy, no_flags, no_payload,
this_node(), prx->node(), no_operation_data, this_node(), prx->node(),
invalid_actor_id, prx->id()); invalid_actor_id, prx->id());
CAF_CHECK_EQUAL(prx->node(), remote_node(0)); CAF_CHECK_EQUAL(prx->node(), remote_node(0));
CAF_CHECK_EQUAL(prx->id(), pseudo_remote(0)->id()); CAF_CHECK_EQUAL(prx->id(), pseudo_remote(0)->id());
...@@ -665,7 +682,7 @@ CAF_TEST(actor_serialize_and_deserialize) { ...@@ -665,7 +682,7 @@ CAF_TEST(actor_serialize_and_deserialize) {
CAF_MESSAGE("send message via BASP (from proxy)"); CAF_MESSAGE("send message via BASP (from proxy)");
auto msg = make_message(actor_cast<actor_addr>(prx)); auto msg = make_message(actor_cast<actor_addr>(prx));
mock(remote_hdl(0), mock(remote_hdl(0),
{basp::message_type::dispatch_message, 0, 0, {basp::message_type::dispatch_message, 0, 0, 0,
prx->node(), this_node(), prx->node(), this_node(),
prx->id(), testee->id()}, prx->id(), testee->id()},
std::vector<actor_id>{}, std::vector<actor_id>{},
...@@ -677,11 +694,9 @@ CAF_TEST(actor_serialize_and_deserialize) { ...@@ -677,11 +694,9 @@ CAF_TEST(actor_serialize_and_deserialize) {
// output buffer must contain the reflected message // output buffer must contain the reflected message
mock() mock()
.expect(remote_hdl(0), .expect(remote_hdl(0),
basp::message_type::dispatch_message, any_vals, uint64_t{0}, basp::message_type::dispatch_message, no_flags, any_vals,
this_node(), prx->node(), no_operation_data, this_node(), prx->node(), testee->id(), prx->id(),
testee->id(), prx->id(), std::vector<actor_id>{}, msg);
std::vector<actor_id>{},
msg);
} }
CAF_TEST(indirect_connections) { CAF_TEST(indirect_connections) {
...@@ -697,23 +712,24 @@ CAF_TEST(indirect_connections) { ...@@ -697,23 +712,24 @@ CAF_TEST(indirect_connections) {
connect_node(1, ax, self()->id()); connect_node(1, ax, self()->id());
// now, an actor from jupiter sends a message to us via mars // now, an actor from jupiter sends a message to us via mars
mock(remote_hdl(1), mock(remote_hdl(1),
{basp::message_type::dispatch_message, 0, 0, {basp::message_type::dispatch_message, 0, 0, 0,
remote_node(0), this_node(), remote_node(0), this_node(),
pseudo_remote(0)->id(), self()->id()}, pseudo_remote(0)->id(), self()->id()},
std::vector<actor_id>{}, std::vector<actor_id>{},
make_message("hello from jupiter!")) make_message("hello from jupiter!"))
// this asks Jupiter if it has a 'SpawnServ' // this asks Jupiter if it has a 'SpawnServ'
.expect(remote_hdl(1), .expect(remote_hdl(1),
basp::message_type::dispatch_message, any_vals, basp::message_type::dispatch_message,
static_cast<uint64_t>(atom("SpawnServ")), basp::header::named_receiver_flag, any_vals,
this_node(), remote_node(0), no_operation_data, this_node(), remote_node(0),
any_vals, std::numeric_limits<actor_id>::max(), any_vals, invalid_actor_id,
spawn_serv_atom,
std::vector<actor_id>{}, std::vector<actor_id>{},
make_message(sys_atom::value, get_atom::value, "info")) make_message(sys_atom::value, get_atom::value, "info"))
// this tells Jupiter that Earth learned the address of one its actors // this tells Jupiter that Earth learned the address of one its actors
.expect(remote_hdl(1), .expect(remote_hdl(1),
basp::message_type::announce_proxy_instance, uint32_t{0}, uint64_t{0}, basp::message_type::announce_proxy, no_flags, no_payload,
this_node(), remote_node(0), no_operation_data, this_node(), remote_node(0),
invalid_actor_id, pseudo_remote(0)->id()); invalid_actor_id, pseudo_remote(0)->id());
CAF_MESSAGE("receive message from jupiter"); CAF_MESSAGE("receive message from jupiter");
self()->receive( self()->receive(
...@@ -725,8 +741,8 @@ CAF_TEST(indirect_connections) { ...@@ -725,8 +741,8 @@ CAF_TEST(indirect_connections) {
mpx()->exec_runnable(); // process forwarded message in basp_broker mpx()->exec_runnable(); // process forwarded message in basp_broker
mock() mock()
.expect(remote_hdl(1), .expect(remote_hdl(1),
basp::message_type::dispatch_message, any_vals, uint64_t{0}, basp::message_type::dispatch_message, no_flags, any_vals,
this_node(), remote_node(0), no_operation_data, this_node(), remote_node(0),
self()->id(), pseudo_remote(0)->id(), self()->id(), pseudo_remote(0)->id(),
std::vector<actor_id>{}, std::vector<actor_id>{},
make_message("hello from earth!")); make_message("hello from earth!"));
...@@ -752,35 +768,36 @@ CAF_TEST(automatic_connection) { ...@@ -752,35 +768,36 @@ CAF_TEST(automatic_connection) {
mpx()->provide_acceptor(4242, ax); mpx()->provide_acceptor(4242, ax);
system.middleman().publish(self(), 4242); system.middleman().publish(self(), 4242);
mpx()->flush_runnables(); // process publish message in basp_broker mpx()->flush_runnables(); // process publish message in basp_broker
// connect to mars CAF_MESSAGE("connect to mars");
connect_node(1, ax, self()->id()); connect_node(1, ax, self()->id());
CAF_CHECK_EQUAL(tbl().lookup_direct(remote_node(1)).id(), remote_hdl(1).id()); CAF_CHECK_EQUAL(tbl().lookup_direct(remote_node(1)).id(), remote_hdl(1).id());
CAF_MESSAGE("simulate that an actor from jupiter " CAF_MESSAGE("simulate that an actor from jupiter "
"sends a message to us via mars"); "sends a message to us via mars");
mock(remote_hdl(1), mock(remote_hdl(1),
{basp::message_type::dispatch_message, 0, 0, {basp::message_type::dispatch_message, 0, 0, 0,
remote_node(0), this_node(), remote_node(0), this_node(),
pseudo_remote(0)->id(), self()->id()}, pseudo_remote(0)->id(), self()->id()},
std::vector<actor_id>{}, std::vector<actor_id>{},
make_message("hello from jupiter!")) make_message("hello from jupiter!"))
.expect(remote_hdl(1), .expect(remote_hdl(1),
basp::message_type::dispatch_message, any_vals, basp::message_type::dispatch_message,
static_cast<uint64_t>(atom("SpawnServ")), basp::header::named_receiver_flag, any_vals, no_operation_data,
this_node(), remote_node(0), this_node(), remote_node(0), any_vals, invalid_actor_id,
any_vals, std::numeric_limits<actor_id>::max(), spawn_serv_atom,
std::vector<actor_id>{}, std::vector<actor_id>{},
make_message(sys_atom::value, get_atom::value, "info")) make_message(sys_atom::value, get_atom::value, "info"))
.expect(remote_hdl(1), .expect(remote_hdl(1),
basp::message_type::dispatch_message, any_vals, basp::message_type::dispatch_message,
static_cast<uint64_t>(atom("ConfigServ")), basp::header::named_receiver_flag, any_vals,
this_node(), remote_node(0), no_operation_data, this_node(), remote_node(0),
any_vals, // actor ID of an actor spawned by the BASP broker any_vals, // actor ID of an actor spawned by the BASP broker
std::numeric_limits<actor_id>::max(), invalid_actor_id,
config_serv_atom,
std::vector<actor_id>{}, std::vector<actor_id>{},
make_message(get_atom::value, "basp.default-connectivity")) make_message(get_atom::value, "basp.default-connectivity"))
.expect(remote_hdl(1), .expect(remote_hdl(1),
basp::message_type::announce_proxy_instance, uint32_t{0}, uint64_t{0}, basp::message_type::announce_proxy, no_flags, no_payload,
this_node(), remote_node(0), no_operation_data, this_node(), remote_node(0),
invalid_actor_id, pseudo_remote(0)->id()); invalid_actor_id, pseudo_remote(0)->id());
CAF_CHECK_EQUAL(mpx()->output_buffer(remote_hdl(1)).size(), 0u); CAF_CHECK_EQUAL(mpx()->output_buffer(remote_hdl(1)).size(), 0u);
CAF_CHECK_EQUAL(tbl().lookup_indirect(remote_node(0)), remote_node(1)); CAF_CHECK_EQUAL(tbl().lookup_indirect(remote_node(0)), remote_node(1));
...@@ -792,7 +809,7 @@ CAF_TEST(automatic_connection) { ...@@ -792,7 +809,7 @@ CAF_TEST(automatic_connection) {
network::address_listing res; network::address_listing res;
res[network::protocol::ipv4].push_back("jupiter"); res[network::protocol::ipv4].push_back("jupiter");
mock(remote_hdl(1), mock(remote_hdl(1),
{basp::message_type::dispatch_message, 0, 0, {basp::message_type::dispatch_message, 0, 0, 0,
this_node(), this_node(), this_node(), this_node(),
invalid_actor_id, connection_helper}, invalid_actor_id, connection_helper},
std::vector<actor_id>{}, std::vector<actor_id>{},
...@@ -805,14 +822,14 @@ CAF_TEST(automatic_connection) { ...@@ -805,14 +822,14 @@ CAF_TEST(automatic_connection) {
CAF_REQUIRE(mpx()->output_buffer(remote_hdl(1)).size() == 0); CAF_REQUIRE(mpx()->output_buffer(remote_hdl(1)).size() == 0);
// send handshake from jupiter // send handshake from jupiter
mock(remote_hdl(0), mock(remote_hdl(0),
{basp::message_type::server_handshake, 0, basp::version, {basp::message_type::server_handshake, 0, 0, basp::version,
remote_node(0), invalid_node_id, remote_node(0), invalid_node_id,
pseudo_remote(0)->id(), invalid_actor_id}, pseudo_remote(0)->id(), invalid_actor_id},
pseudo_remote(0)->id(), pseudo_remote(0)->id(),
uint32_t{0}) uint32_t{0})
.expect(remote_hdl(0), .expect(remote_hdl(0),
basp::message_type::client_handshake, uint32_t{0}, uint64_t{0}, basp::message_type::client_handshake, no_flags, no_payload,
this_node(), remote_node(0), no_operation_data, this_node(), remote_node(0),
invalid_actor_id, invalid_actor_id); invalid_actor_id, invalid_actor_id);
CAF_CHECK_EQUAL(tbl().lookup_indirect(remote_node(0)), invalid_node_id); CAF_CHECK_EQUAL(tbl().lookup_indirect(remote_node(0)), invalid_node_id);
CAF_CHECK_EQUAL(tbl().lookup_indirect(remote_node(1)), invalid_node_id); CAF_CHECK_EQUAL(tbl().lookup_indirect(remote_node(1)), invalid_node_id);
...@@ -829,8 +846,8 @@ CAF_TEST(automatic_connection) { ...@@ -829,8 +846,8 @@ CAF_TEST(automatic_connection) {
CAF_MESSAGE("response message must take direct route now"); CAF_MESSAGE("response message must take direct route now");
mock() mock()
.expect(remote_hdl(0), .expect(remote_hdl(0),
basp::message_type::dispatch_message, any_vals, uint64_t{0}, basp::message_type::dispatch_message, no_flags, any_vals,
this_node(), remote_node(0), no_operation_data, this_node(), remote_node(0),
self()->id(), pseudo_remote(0)->id(), self()->id(), pseudo_remote(0)->id(),
std::vector<actor_id>{}, std::vector<actor_id>{},
make_message("hello from earth!")); make_message("hello from earth!"));
......
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