Unverified Commit 493ec8b2 authored by Dominik Charousset's avatar Dominik Charousset Committed by GitHub

Merge pull request #32

No copy refactoring
parents 4da5fec8 3efaa0c0
...@@ -20,6 +20,7 @@ set(LIBCAF_NET_SRCS ...@@ -20,6 +20,7 @@ set(LIBCAF_NET_SRCS
src/application.cpp src/application.cpp
src/convert_ip_endpoint.cpp src/convert_ip_endpoint.cpp
src/datagram_socket.cpp src/datagram_socket.cpp
src/defaults.cpp
src/ec.cpp src/ec.cpp
src/endpoint_manager.cpp src/endpoint_manager.cpp
src/header.cpp src/header.cpp
...@@ -30,6 +31,7 @@ set(LIBCAF_NET_SRCS ...@@ -30,6 +31,7 @@ set(LIBCAF_NET_SRCS
src/net/endpoint_manager_queue.cpp src/net/endpoint_manager_queue.cpp
src/net/middleman.cpp src/net/middleman.cpp
src/net/middleman_backend.cpp src/net/middleman_backend.cpp
src/net/packet_writer.cpp
src/network_socket.cpp src/network_socket.cpp
src/pipe_socket.cpp src/pipe_socket.cpp
src/pollset_updater.cpp src/pollset_updater.cpp
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include "caf/net/basp/header.hpp" #include "caf/net/basp/header.hpp"
#include "caf/net/basp/message_type.hpp" #include "caf/net/basp/message_type.hpp"
#include "caf/net/endpoint_manager.hpp" #include "caf/net/endpoint_manager.hpp"
#include "caf/net/packet_writer.hpp"
#include "caf/net/receive_policy.hpp" #include "caf/net/receive_policy.hpp"
#include "caf/node_id.hpp" #include "caf/node_id.hpp"
#include "caf/proxy_registry.hpp" #include "caf/proxy_registry.hpp"
...@@ -56,8 +57,6 @@ public: ...@@ -56,8 +57,6 @@ public:
using byte_span = span<const byte>; using byte_span = span<const byte>;
using write_packet_callback = callback<byte_span, byte_span>;
struct test_tag {}; struct test_tag {};
// -- constructors, destructors, and assignment operators -------------------- // -- constructors, destructors, and assignment operators --------------------
...@@ -77,65 +76,37 @@ public: ...@@ -77,65 +76,37 @@ public:
if (!std::is_base_of<test_tag, Parent>::value) if (!std::is_base_of<test_tag, Parent>::value)
manager_ = &parent.manager(); manager_ = &parent.manager();
// Write handshake. // Write handshake.
if (auto err = generate_handshake()) auto hdr = parent.next_header_buffer();
auto payload = parent.next_payload_buffer();
if (auto err = generate_handshake(payload))
return err; return err;
auto hdr = to_bytes(header{message_type::handshake, to_bytes(header{message_type::handshake,
static_cast<uint32_t>(buf_.size()), version}); static_cast<uint32_t>(payload.size()), version},
parent.write_packet(hdr, buf_); hdr);
parent.write_packet(hdr, payload);
parent.transport().configure_read(receive_policy::exactly(header_size)); parent.transport().configure_read(receive_policy::exactly(header_size));
return none; return none;
} }
template <class Parent> error write_message(packet_writer& writer,
error write_message(Parent& parent, std::unique_ptr<endpoint_manager_queue::message> ptr);
std::unique_ptr<endpoint_manager_queue::message> ptr) {
auto write_packet = make_callback([&](byte_span hdr, byte_span payload) {
parent.write_packet(hdr, payload);
return none;
});
return write(write_packet, std::move(ptr));
}
template <class Parent> template <class Parent>
error handle_data(Parent& parent, byte_span bytes) { error handle_data(Parent& parent, byte_span bytes) {
auto write_packet = make_callback([&](byte_span hdr, byte_span payload) { static_assert(std::is_base_of<packet_writer, Parent>::value,
parent.write_packet(hdr, payload); "parent must implement packet_writer");
return none;
});
size_t next_read_size = header_size; size_t next_read_size = header_size;
if (auto err = handle(next_read_size, write_packet, bytes)) if (auto err = handle(next_read_size, parent, bytes))
return err; return err;
parent.transport().configure_read(receive_policy::exactly(next_read_size)); parent.transport().configure_read(receive_policy::exactly(next_read_size));
return none; return none;
} }
template <class Parent> void resolve(packet_writer& writer, string_view path, const actor& listener);
void resolve(Parent& parent, string_view path, actor listener) {
auto write_packet = make_callback([&](byte_span hdr, byte_span payload) {
parent.write_packet(hdr, payload);
return none;
});
resolve_remote_path(write_packet, path, listener);
}
template <class Parent> static void new_proxy(packet_writer& writer, actor_id id);
void new_proxy(Parent& parent, actor_id id) {
header hdr{message_type::monitor_message, 0, static_cast<uint64_t>(id)};
auto bytes = to_bytes(hdr);
parent.write_packet(make_span(bytes), span<const byte>{});
}
template <class Parent> void local_actor_down(packet_writer& writer, actor_id id, error reason);
void local_actor_down(Parent& parent, actor_id id, error reason) {
buf_.clear();
serializer_impl<buffer_type> sink{system(), buf_};
if (auto err = sink(reason))
CAF_RAISE_ERROR("unable to serialize an error");
header hdr{message_type::down_message, static_cast<uint32_t>(buf_.size()),
static_cast<uint64_t>(id)};
auto bytes = to_bytes(hdr);
parent.write_packet(make_span(bytes), make_span(buf_));
}
template <class Parent> template <class Parent>
void timeout(Parent&, atom_value, uint64_t) { void timeout(Parent&, atom_value, uint64_t) {
...@@ -146,16 +117,13 @@ public: ...@@ -146,16 +117,13 @@ public:
// nop // nop
} }
static expected<std::vector<byte>> serialize(actor_system& sys, static expected<buffer_type> serialize(actor_system& sys,
const type_erased_tuple& x); const type_erased_tuple& x);
// -- utility functions ------------------------------------------------------ // -- utility functions ------------------------------------------------------
strong_actor_ptr resolve_local_path(string_view path); strong_actor_ptr resolve_local_path(string_view path);
void resolve_remote_path(write_packet_callback& write_packet,
string_view path, actor listener);
// -- properties ------------------------------------------------------------- // -- properties -------------------------------------------------------------
connection_state state() const noexcept { connection_state state() const noexcept {
...@@ -167,39 +135,31 @@ public: ...@@ -167,39 +135,31 @@ public:
} }
private: private:
// -- handling of outgoing messages ------------------------------------------
error write(write_packet_callback& write_packet,
std::unique_ptr<endpoint_manager_queue::message> ptr);
// -- handling of incoming messages ------------------------------------------ // -- handling of incoming messages ------------------------------------------
error handle(size_t& next_read_size, write_packet_callback& write_packet, error handle(size_t& next_read_size, packet_writer& writer, byte_span bytes);
byte_span bytes);
error handle(write_packet_callback& write_packet, header hdr, error handle(packet_writer& writer, header hdr, byte_span payload);
byte_span payload);
error handle_handshake(write_packet_callback& write_packet, header hdr, error handle_handshake(packet_writer& writer, header hdr, byte_span payload);
byte_span payload);
error handle_actor_message(write_packet_callback& write_packet, header hdr, error handle_actor_message(packet_writer& writer, header hdr,
byte_span payload); byte_span payload);
error handle_resolve_request(write_packet_callback& write_packet, header hdr, error handle_resolve_request(packet_writer& writer, header rec_hdr,
byte_span payload); byte_span received);
error handle_resolve_response(write_packet_callback& write_packet, header hdr, error handle_resolve_response(packet_writer& writer, header received_hdr,
byte_span payload); byte_span received);
error handle_monitor_message(write_packet_callback& write_packet, header hdr, error handle_monitor_message(packet_writer& writer, header received_hdr,
byte_span payload); byte_span received);
error handle_down_message(write_packet_callback& write_packet, header hdr, error handle_down_message(packet_writer& writer, header received_hdr,
byte_span payload); byte_span received);
/// Writes the handshake payload to `buf_`. /// Writes the handshake payload to `buf_`.
error generate_handshake(); error generate_handshake(buffer_type& buf);
// -- member variables ------------------------------------------------------- // -- member variables -------------------------------------------------------
...@@ -212,14 +172,11 @@ private: ...@@ -212,14 +172,11 @@ private:
/// Caches the last header while waiting for the matching payload. /// Caches the last header while waiting for the matching payload.
header hdr_; header hdr_;
/// Re-usable buffer for storing payloads.
buffer_type buf_;
/// Stores the ID of our peer. /// Stores the ID of our peer.
node_id peer_id_; node_id peer_id_;
/// Tracks which local actors our peer monitors. /// Tracks which local actors our peer monitors.
std::unordered_set<actor_addr> monitored_actors_; std::unordered_set<actor_addr> monitored_actors_; // TODO: this is unused
/// Caches actor handles obtained via `resolve`. /// Caches actor handles obtained via `resolve`.
std::unordered_map<uint64_t, response_promise> pending_resolves_; std::unordered_map<uint64_t, response_promise> pending_resolves_;
......
...@@ -78,6 +78,10 @@ struct header : detail::comparable<header> { ...@@ -78,6 +78,10 @@ struct header : detail::comparable<header> {
/// @relates header /// @relates header
std::array<byte, header_size> to_bytes(header x); std::array<byte, header_size> to_bytes(header x);
/// Serializes a header to a byte representation.
/// @relates header
void to_bytes(header x, std::vector<byte>& buf);
/// @relates header /// @relates header
template <class Inspector> template <class Inspector>
typename Inspector::result_type inspect(Inspector& f, header& x) { typename Inspector::result_type inspect(Inspector& f, header& x) {
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2018 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#pragma once
#include <cstddef>
// -- hard-coded default values for various CAF options ------------------------
namespace caf {
namespace defaults {
namespace middleman {
/// Maximum number of cached buffers for sending payloads.
extern const size_t max_payload_buffers;
/// Maximum number of cached buffers for sending headers.
extern const size_t max_header_buffers;
} // namespace middleman
} // namespace defaults
} // namespace caf
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2019 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#pragma once
#include <vector>
#include "caf/byte.hpp"
#include "caf/net/fwd.hpp"
#include "caf/span.hpp"
namespace caf {
namespace net {
/// Implements an interface for packet writing in application-layers.
class packet_writer {
public:
using buffer_type = std::vector<byte>;
virtual ~packet_writer();
/// Returns a buffer for writing header information.
virtual buffer_type next_header_buffer() = 0;
/// Returns a buffer for writing payload content.
virtual buffer_type next_payload_buffer() = 0;
/// Convenience function to write a packet consisting of multiple buffers.
/// @param buffers all buffers for the packet. The first buffer is a header
/// buffer, the other buffers are payload buffer.
/// @warning this function takes ownership of `buffers`.
template <class... Ts>
void write_packet(Ts&... buffers) {
buffer_type* bufs[] = {&buffers...};
write_impl(make_span(bufs, sizeof...(Ts)));
}
protected:
/// Implementing function for `write_packet`.
/// @param buffers a `span` containing all buffers of a packet.
virtual void write_impl(span<buffer_type*> buffers) = 0;
};
} // namespace net
} // namespace caf
...@@ -18,6 +18,8 @@ ...@@ -18,6 +18,8 @@
#pragma once #pragma once
#include "caf/net/packet_writer.hpp"
#include "caf/byte.hpp" #include "caf/byte.hpp"
#include "caf/span.hpp" #include "caf/span.hpp"
...@@ -25,9 +27,9 @@ namespace caf { ...@@ -25,9 +27,9 @@ namespace caf {
namespace net { namespace net {
/// Implements the interface for transport and application policies and /// Implements the interface for transport and application policies and
/// dispatches member functions either to `decorator` or `parent`. /// dispatches member functions either to `object` or `parent`.
template <class Object, class Parent> template <class Object, class Parent>
class write_packet_decorator { class packet_writer_decorator final : public packet_writer {
public: public:
// -- member types ----------------------------------------------------------- // -- member types -----------------------------------------------------------
...@@ -37,7 +39,7 @@ public: ...@@ -37,7 +39,7 @@ public:
// -- constructors, destructors, and assignment operators -------------------- // -- constructors, destructors, and assignment operators --------------------
write_packet_decorator(Object& object, Parent& parent) packet_writer_decorator(Object& object, Parent& parent)
: object_(object), parent_(parent) { : object_(object), parent_(parent) {
// nop // nop
} }
...@@ -56,15 +58,16 @@ public: ...@@ -56,15 +58,16 @@ public:
return parent_.manager(); return parent_.manager();
} }
// -- member functions ------------------------------------------------------- buffer_type next_header_buffer() override {
return transport().next_header_buffer();
}
template <class... Ts> buffer_type next_payload_buffer() override {
void write_packet(span<const byte> header, span<const byte> payload, return transport().next_payload_buffer();
Ts&&... xs) {
parent_.write_packet(header, payload, std::forward<Ts>(xs)...,
object_.id());
} }
// -- member functions -------------------------------------------------------
void cancel_timeout(atom_value type, uint64_t id) { void cancel_timeout(atom_value type, uint64_t id) {
parent_.cancel_timeout(type, id); parent_.cancel_timeout(type, id);
} }
...@@ -74,14 +77,19 @@ public: ...@@ -74,14 +77,19 @@ public:
return parent_.set_timeout(tout, type, std::forward<Ts>(xs)...); return parent_.set_timeout(tout, type, std::forward<Ts>(xs)...);
} }
protected:
void write_impl(span<buffer_type*> buffers) override {
parent_.write_packet(object_.id(), buffers);
}
private: private:
Object& object_; Object& object_;
Parent& parent_; Parent& parent_;
}; };
template <class Object, class Parent> template <class Object, class Parent>
write_packet_decorator<Object, Parent> packet_writer_decorator<Object, Parent>
make_write_packet_decorator(Object& object, Parent& parent) { make_packet_writer_decorator(Object& object, Parent& parent) {
return {object, parent}; return {object, parent};
} }
......
...@@ -18,10 +18,13 @@ ...@@ -18,10 +18,13 @@
#pragma once #pragma once
#include "caf/actor_system_config.hpp"
#include "caf/byte.hpp" #include "caf/byte.hpp"
#include "caf/error.hpp" #include "caf/error.hpp"
#include "caf/expected.hpp"
#include "caf/fwd.hpp" #include "caf/fwd.hpp"
#include "caf/logger.hpp" #include "caf/logger.hpp"
#include "caf/net/defaults.hpp"
#include "caf/net/endpoint_manager.hpp" #include "caf/net/endpoint_manager.hpp"
#include "caf/net/receive_policy.hpp" #include "caf/net/receive_policy.hpp"
#include "caf/net/stream_socket.hpp" #include "caf/net/stream_socket.hpp"
...@@ -45,6 +48,10 @@ public: ...@@ -45,6 +48,10 @@ public:
using worker_type = transport_worker<application_type>; using worker_type = transport_worker<application_type>;
using buffer_type = std::vector<byte>;
using buffer_cache_type = std::vector<buffer_type>;
// -- constructors, destructors, and assignment operators -------------------- // -- constructors, destructors, and assignment operators --------------------
stream_transport(stream_socket handle, application_type application) stream_transport(stream_socket handle, application_type application)
...@@ -87,6 +94,13 @@ public: ...@@ -87,6 +94,13 @@ public:
template <class Parent> template <class Parent>
error init(Parent& parent) { error init(Parent& parent) {
manager_ = &parent; manager_ = &parent;
auto& cfg = system().config();
auto max_header_bufs = get_or(cfg, "middleman.max-header-buffers",
defaults::middleman::max_header_buffers);
header_bufs_.reserve(max_header_bufs);
auto max_payload_bufs = get_or(cfg, "middleman.max-payload-buffers",
defaults::middleman::max_payload_buffers);
payload_bufs_.reserve(max_payload_bufs);
if (auto err = worker_.init(*this)) if (auto err = worker_.init(*this))
return err; return err;
return none; return none;
...@@ -198,49 +212,96 @@ public: ...@@ -198,49 +212,96 @@ public:
prepare_next_read(); prepare_next_read();
} }
void write_packet(span<const byte> header, span<const byte> payload, void write_packet(unit_t, span<buffer_type*> buffers) {
typename worker_type::id_type) { CAF_ASSERT(!buffers.empty());
if (write_buf_.empty()) if (write_queue_.empty())
manager().register_writing(); manager().register_writing();
write_buf_.insert(write_buf_.end(), header.begin(), header.end()); // By convention, the first buffer is a header buffer. Every other buffer is
write_buf_.insert(write_buf_.end(), payload.begin(), payload.end()); // a payload buffer.
auto i = buffers.begin();
write_queue_.emplace_back(true, std::move(*(*i++)));
while (i != buffers.end())
write_queue_.emplace_back(false, std::move(*(*i++)));
}
// -- buffer management ------------------------------------------------------
buffer_type next_header_buffer() {
return next_buffer_impl(header_bufs_);
}
buffer_type next_payload_buffer() {
return next_buffer_impl(payload_bufs_);
} }
private: private:
// -- private member functions ----------------------------------------------- // -- utility functions ------------------------------------------------------
static buffer_type next_buffer_impl(buffer_cache_type cache) {
if (cache.empty()) {
return {};
}
auto buf = std::move(cache.back());
cache.pop_back();
return buf;
}
bool write_some() { bool write_some() {
if (write_buf_.empty()) CAF_LOG_TRACE(CAF_ARG(handle_.id));
if (write_queue_.empty())
return false; return false;
auto len = write_buf_.size() - written_; // Helper function to sort empty buffers back into the right caches.
auto buf = write_buf_.data() + written_; auto recycle = [&]() {
CAF_LOG_TRACE(CAF_ARG(handle_.id) << CAF_ARG(len)); auto& front = write_queue_.front();
auto ret = write(handle_, make_span(buf, len)); auto& is_header = front.first;
if (auto num_bytes = get_if<size_t>(&ret)) { auto& buf = front.second;
CAF_LOG_DEBUG(CAF_ARG(len) << CAF_ARG(handle_.id) << CAF_ARG(*num_bytes)); written_ = 0;
// Update state. buf.clear();
written_ += *num_bytes; if (is_header) {
if (written_ >= write_buf_.size()) { if (header_bufs_.size() < header_bufs_.capacity())
written_ = 0; header_bufs_.emplace_back(std::move(buf));
write_buf_.clear(); } else if (payload_bufs_.size() < payload_bufs_.capacity()) {
return false; payload_bufs_.emplace_back(std::move(buf));
} }
} else { write_queue_.pop_front();
auto err = get<sec>(ret); };
if (err != sec::unavailable_or_would_block) { // Write buffers from the write_queue_ for as long as possible.
CAF_LOG_DEBUG("send failed" << CAF_ARG(err)); do {
worker_.handle_error(err); auto& buf = write_queue_.front().second;
return false; CAF_ASSERT(!buf.empty());
auto data = buf.data() + written_;
auto len = buf.size() - written_;
auto write_ret = write(handle_, make_span(data, len));
if (auto num_bytes = get_if<size_t>(&write_ret)) {
CAF_LOG_DEBUG(CAF_ARG(handle_.id) << CAF_ARG(*num_bytes));
if (*num_bytes + written_ >= buf.size()) {
recycle();
written_ = 0;
} else {
written_ += *num_bytes;
return false;
}
} else {
auto err = get<sec>(write_ret);
if (err != sec::unavailable_or_would_block) {
CAF_LOG_DEBUG("send failed" << CAF_ARG(err));
worker_.handle_error(err);
return false;
}
return true;
} }
} } while (!write_queue_.empty());
return true; return false;
} }
worker_type worker_; worker_type worker_;
stream_socket handle_; stream_socket handle_;
std::vector<byte> read_buf_; buffer_cache_type header_bufs_;
std::vector<byte> write_buf_; buffer_cache_type payload_bufs_;
buffer_type read_buf_;
std::deque<std::pair<bool, buffer_type>> write_queue_;
// TODO implement retries using this member! // TODO implement retries using this member!
// size_t max_consecutive_reads_; // size_t max_consecutive_reads_;
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
#include "caf/ip_endpoint.hpp" #include "caf/ip_endpoint.hpp"
#include "caf/net/endpoint_manager.hpp" #include "caf/net/endpoint_manager.hpp"
#include "caf/net/fwd.hpp" #include "caf/net/fwd.hpp"
#include "caf/net/write_packet_decorator.hpp" #include "caf/net/packet_writer_decorator.hpp"
#include "caf/span.hpp" #include "caf/span.hpp"
#include "caf/unit.hpp" #include "caf/unit.hpp"
...@@ -64,46 +64,46 @@ public: ...@@ -64,46 +64,46 @@ public:
template <class Parent> template <class Parent>
error init(Parent& parent) { error init(Parent& parent) {
auto decorator = make_write_packet_decorator(*this, parent); auto writer = make_packet_writer_decorator(*this, parent);
return application_.init(decorator); return application_.init(writer);
} }
template <class Parent> template <class Parent>
error handle_data(Parent& parent, span<const byte> data) { error handle_data(Parent& parent, span<const byte> data) {
auto decorator = make_write_packet_decorator(*this, parent); auto writer = make_packet_writer_decorator(*this, parent);
return application_.handle_data(decorator, data); return application_.handle_data(writer, data);
} }
template <class Parent> template <class Parent>
void write_message(Parent& parent, void write_message(Parent& parent,
std::unique_ptr<endpoint_manager_queue::message> msg) { std::unique_ptr<endpoint_manager_queue::message> msg) {
auto decorator = make_write_packet_decorator(*this, parent); auto writer = make_packet_writer_decorator(*this, parent);
application_.write_message(decorator, std::move(msg)); application_.write_message(writer, std::move(msg));
} }
template <class Parent> template <class Parent>
void resolve(Parent& parent, string_view path, const actor& listener) { void resolve(Parent& parent, string_view path, const actor& listener) {
auto decorator = make_write_packet_decorator(*this, parent); auto writer = make_packet_writer_decorator(*this, parent);
application_.resolve(decorator, path, listener); application_.resolve(writer, path, listener);
} }
template <class Parent> template <class Parent>
void new_proxy(Parent& parent, const node_id&, actor_id id) { void new_proxy(Parent& parent, const node_id&, actor_id id) {
auto decorator = make_write_packet_decorator(*this, parent); auto writer = make_packet_writer_decorator(*this, parent);
application_.new_proxy(decorator, id); application_.new_proxy(writer, id);
} }
template <class Parent> template <class Parent>
void local_actor_down(Parent& parent, const node_id&, actor_id id, void local_actor_down(Parent& parent, const node_id&, actor_id id,
error reason) { error reason) {
auto decorator = make_write_packet_decorator(*this, parent); auto writer = make_packet_writer_decorator(*this, parent);
application_.local_actor_down(decorator, id, std::move(reason)); application_.local_actor_down(writer, id, std::move(reason));
} }
template <class Parent> template <class Parent>
void timeout(Parent& parent, atom_value value, uint64_t id) { void timeout(Parent& parent, atom_value value, uint64_t id) {
auto decorator = make_write_packet_decorator(*this, parent); auto writer = make_packet_writer_decorator(*this, parent);
application_.timeout(decorator, value, id); application_.timeout(writer, value, id);
} }
void handle_error(sec error) { void handle_error(sec error) {
......
...@@ -24,8 +24,8 @@ ...@@ -24,8 +24,8 @@
#include "caf/ip_endpoint.hpp" #include "caf/ip_endpoint.hpp"
#include "caf/net/endpoint_manager.hpp" #include "caf/net/endpoint_manager.hpp"
#include "caf/net/fwd.hpp" #include "caf/net/fwd.hpp"
#include "caf/net/packet_writer_decorator.hpp"
#include "caf/net/transport_worker.hpp" #include "caf/net/transport_worker.hpp"
#include "caf/net/write_packet_decorator.hpp"
#include "caf/span.hpp" #include "caf/span.hpp"
#include "caf/unit.hpp" #include "caf/unit.hpp"
......
This diff is collapsed.
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2018 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include "caf/net/defaults.hpp"
namespace caf {
namespace defaults {
namespace middleman {
const size_t max_payload_buffers = 100;
const size_t max_header_buffers = 10;
} // namespace middleman
} // namespace defaults
} // namespace caf
...@@ -28,6 +28,18 @@ namespace caf { ...@@ -28,6 +28,18 @@ namespace caf {
namespace net { namespace net {
namespace basp { namespace basp {
namespace {
void to_bytes_impl(const header& x, byte* ptr) {
*ptr = static_cast<byte>(x.type);
auto payload_len = detail::to_network_order(x.payload_len);
memcpy(ptr + 1, &payload_len, sizeof(payload_len));
auto operation_data = detail::to_network_order(x.operation_data);
memcpy(ptr + 5, &operation_data, sizeof(operation_data));
}
} // namespace
int header::compare(header other) const noexcept { int header::compare(header other) const noexcept {
auto x = to_bytes(*this); auto x = to_bytes(*this);
auto y = to_bytes(other); auto y = to_bytes(other);
...@@ -47,16 +59,16 @@ header header::from_bytes(span<const byte> bytes) { ...@@ -47,16 +59,16 @@ header header::from_bytes(span<const byte> bytes) {
} }
std::array<byte, header_size> to_bytes(header x) { std::array<byte, header_size> to_bytes(header x) {
std::array<byte, header_size> result; std::array<byte, header_size> result{};
auto ptr = result.data(); to_bytes_impl(x, result.data());
*ptr = static_cast<byte>(x.type);
auto payload_len = detail::to_network_order(x.payload_len);
memcpy(ptr + 1, &payload_len, sizeof(payload_len));
auto operation_data = detail::to_network_order(x.operation_data);
memcpy(ptr + 5, &operation_data, sizeof(operation_data));
return result; return result;
} }
void to_bytes(header x, std::vector<byte>& buf) {
buf.resize(header_size);
to_bytes_impl(x, buf.data());
}
} // namespace basp } // namespace basp
} // namespace net } // namespace net
} // namespace caf } // namespace caf
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2019 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include "caf/net/packet_writer.hpp"
namespace caf {
namespace net {
packet_writer::~packet_writer() {
// nop
}
} // namespace net
} // namespace caf
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include "caf/net/basp/connection_state.hpp" #include "caf/net/basp/connection_state.hpp"
#include "caf/net/basp/constants.hpp" #include "caf/net/basp/constants.hpp"
#include "caf/net/basp/ec.hpp" #include "caf/net/basp/ec.hpp"
#include "caf/net/packet_writer.hpp"
#include "caf/none.hpp" #include "caf/none.hpp"
#include "caf/uri.hpp" #include "caf/uri.hpp"
...@@ -43,7 +44,8 @@ namespace { ...@@ -43,7 +44,8 @@ namespace {
struct fixture : test_coordinator_fixture<>, struct fixture : test_coordinator_fixture<>,
proxy_registry::backend, proxy_registry::backend,
basp::application::test_tag { basp::application::test_tag,
public packet_writer {
using buffer_type = std::vector<byte>; using buffer_type = std::vector<byte>;
fixture() : proxies(sys, *this), app(proxies) { fixture() : proxies(sys, *this), app(proxies) {
...@@ -66,11 +68,6 @@ struct fixture : test_coordinator_fixture<>, ...@@ -66,11 +68,6 @@ struct fixture : test_coordinator_fixture<>,
input = to_buf(xs...); input = to_buf(xs...);
} }
void write_packet(span<const byte> hdr, span<const byte> payload) {
output.insert(output.end(), hdr.begin(), hdr.end());
output.insert(output.end(), payload.begin(), payload.end());
}
void handle_handshake() { void handle_handshake() {
CAF_CHECK_EQUAL(app.state(), CAF_CHECK_EQUAL(app.state(),
basp::connection_state::await_handshake_header); basp::connection_state::await_handshake_header);
...@@ -114,6 +111,14 @@ struct fixture : test_coordinator_fixture<>, ...@@ -114,6 +111,14 @@ struct fixture : test_coordinator_fixture<>,
CAF_FAIL("unexpected function call"); CAF_FAIL("unexpected function call");
} }
buffer_type next_payload_buffer() override {
return {};
}
buffer_type next_header_buffer() override {
return {};
}
template <class... Ts> template <class... Ts>
void configure_read(Ts...) { void configure_read(Ts...) {
// nop // nop
...@@ -130,6 +135,12 @@ struct fixture : test_coordinator_fixture<>, ...@@ -130,6 +135,12 @@ struct fixture : test_coordinator_fixture<>,
// nop // nop
} }
protected:
void write_impl(span<buffer_type*> buffers) override {
for (auto buf : buffers)
output.insert(output.end(), buf->begin(), buf->end());
}
buffer_type input; buffer_type input;
buffer_type output; buffer_type output;
......
...@@ -71,10 +71,10 @@ public: ...@@ -71,10 +71,10 @@ public:
return none; return none;
} }
template <class Transport> template <class Parent>
void write_message(Transport& transport, void write_message(Parent& parent,
std::unique_ptr<endpoint_manager_queue::message> msg) { std::unique_ptr<endpoint_manager_queue::message> ptr) {
transport.write_packet(span<byte>{}, msg->payload); parent.write_packet(ptr->payload);
} }
template <class Parent> template <class Parent>
......
...@@ -43,6 +43,8 @@ using namespace caf::policy; ...@@ -43,6 +43,8 @@ using namespace caf::policy;
namespace { namespace {
using buffer_type = std::vector<byte>;
struct fixture : test_coordinator_fixture<>, host_fixture { struct fixture : test_coordinator_fixture<>, host_fixture {
fixture() { fixture() {
mpx = std::make_shared<multiplexer>(); mpx = std::make_shared<multiplexer>();
...@@ -98,13 +100,15 @@ public: ...@@ -98,13 +100,15 @@ public:
template <class Parent> template <class Parent>
void write_message(Parent& parent, void write_message(Parent& parent,
std::unique_ptr<endpoint_manager_queue::message> msg) { std::unique_ptr<endpoint_manager_queue::message> ptr) {
// Ignore proxy announcement messages. // Ignore proxy announcement messages.
if (msg->msg == nullptr) if (ptr->msg == nullptr)
return; return;
header_type header{static_cast<uint32_t>(msg->payload.size())}; auto header_buf = parent.next_header_buffer();
std::vector<byte> payload(msg->payload.begin(), msg->payload.end()); serializer_impl<buffer_type> sink{sys_, header_buf};
parent.write_packet(as_bytes(make_span(&header, 1)), make_span(payload)); header_type header{static_cast<uint32_t>(ptr->payload.size())};
sink(header);
parent.write_packet(header_buf, ptr->payload);
} }
static expected<std::vector<byte>> serialize(actor_system& sys, static expected<std::vector<byte>> serialize(actor_system& sys,
...@@ -147,7 +151,8 @@ public: ...@@ -147,7 +151,8 @@ public:
} else { } else {
if (data.size() != sizeof(header_type)) if (data.size() != sizeof(header_type))
CAF_FAIL(""); CAF_FAIL("");
memcpy(&header_, data.data(), sizeof(header_type)); binary_deserializer source{nullptr, data};
source(header_);
if (header_.payload == 0) if (header_.payload == 0)
Base::handle_packet(parent, header_, span<const byte>{}); Base::handle_packet(parent, header_, span<const byte>{});
else else
...@@ -187,8 +192,8 @@ public: ...@@ -187,8 +192,8 @@ public:
// nop // nop
} }
void handle_error(sec) { void handle_error(sec sec) {
// nop CAF_FAIL("handle_error called: " << CAF_ARG(sec));
} }
private: private:
......
...@@ -37,6 +37,8 @@ using namespace caf::net; ...@@ -37,6 +37,8 @@ using namespace caf::net;
namespace { namespace {
using buffer_type = std::vector<byte>;
constexpr string_view hello_test = "hello test!"; constexpr string_view hello_test = "hello test!";
struct application_result { struct application_result {
...@@ -72,7 +74,8 @@ public: ...@@ -72,7 +74,8 @@ public:
template <class Parent> template <class Parent>
void write_message(Parent& parent, void write_message(Parent& parent,
std::unique_ptr<endpoint_manager_queue::message> msg) { std::unique_ptr<endpoint_manager_queue::message> msg) {
parent.write_packet(span<const byte>{}, msg->payload); auto header_buffer = parent.next_header_buffer();
parent.write_packet(header_buffer, msg->payload);
} }
template <class Parent> template <class Parent>
...@@ -118,16 +121,29 @@ public: ...@@ -118,16 +121,29 @@ public:
using application_type = dummy_application; using application_type = dummy_application;
dummy_transport(std::shared_ptr<transport_result> res) : res_(res) { dummy_transport(std::shared_ptr<transport_result> res)
: res_(std::move(res)) {
// nop // nop
} }
void write_packet(span<const byte> header, span<const byte> payload, void write_packet(ip_endpoint ep, span<buffer_type*> buffers) {
ip_endpoint ep) {
auto& buf = res_->packet_buffer;
buf.insert(buf.begin(), header.begin(), header.end());
buf.insert(buf.begin(), payload.begin(), payload.end());
res_->ep = ep; res_->ep = ep;
auto& packet_buf = res_->packet_buffer;
packet_buf.clear();
for (auto buf : buffers)
packet_buf.insert(packet_buf.end(), buf->begin(), buf->end());
}
transport_type& transport() {
return *this;
}
std::vector<byte> next_header_buffer() {
return {};
}
std::vector<byte> next_payload_buffer() {
return {};
} }
private: private:
......
...@@ -33,6 +33,8 @@ using namespace caf::net; ...@@ -33,6 +33,8 @@ using namespace caf::net;
namespace { namespace {
using buffer_type = std::vector<byte>;
constexpr string_view hello_test = "hello_test"; constexpr string_view hello_test = "hello_test";
struct dummy_actor : public monitorable_actor { struct dummy_actor : public monitorable_actor {
...@@ -47,7 +49,7 @@ struct dummy_actor : public monitorable_actor { ...@@ -47,7 +49,7 @@ struct dummy_actor : public monitorable_actor {
class dummy_application { class dummy_application {
public: public:
dummy_application(std::shared_ptr<std::vector<byte>> rec_buf, uint8_t id) dummy_application(std::shared_ptr<buffer_type> rec_buf, uint8_t id)
: rec_buf_(std::move(rec_buf)), : rec_buf_(std::move(rec_buf)),
id_(id){ id_(id){
// nop // nop
...@@ -61,11 +63,12 @@ public: ...@@ -61,11 +63,12 @@ public:
return none; return none;
} }
template <class Transport> template <class Parent>
void write_message(Transport& transport, void write_message(Parent& parent,
std::unique_ptr<endpoint_manager_queue::message> msg) { std::unique_ptr<endpoint_manager_queue::message> msg) {
rec_buf_->push_back(static_cast<byte>(id_)); rec_buf_->push_back(static_cast<byte>(id_));
transport.write_packet(span<byte>{}, make_span(msg->payload)); auto header_buf = parent.next_header_buffer();
parent.write_packet(header_buf, msg->payload);
} }
template <class Parent> template <class Parent>
...@@ -88,13 +91,13 @@ public: ...@@ -88,13 +91,13 @@ public:
rec_buf_->push_back(static_cast<byte>(id_)); rec_buf_->push_back(static_cast<byte>(id_));
} }
static expected<std::vector<byte>> serialize(actor_system&, static expected<buffer_type> serialize(actor_system&,
const type_erased_tuple&) { const type_erased_tuple&) {
return std::vector<byte>{}; return buffer_type{};
} }
private: private:
std::shared_ptr<std::vector<byte>> rec_buf_; std::shared_ptr<buffer_type> rec_buf_;
uint8_t id_; uint8_t id_;
}; };
...@@ -102,8 +105,8 @@ struct dummy_application_factory { ...@@ -102,8 +105,8 @@ struct dummy_application_factory {
public: public:
using application_type = dummy_application; using application_type = dummy_application;
dummy_application_factory(std::shared_ptr<std::vector<byte>> buf) dummy_application_factory(std::shared_ptr<buffer_type> buf)
: buf_(buf), application_cnt_(0) { : buf_(std::move(buf)), application_cnt_(0) {
// nop // nop
} }
...@@ -112,7 +115,7 @@ public: ...@@ -112,7 +115,7 @@ public:
} }
private: private:
std::shared_ptr<std::vector<byte>> buf_; std::shared_ptr<buffer_type> buf_;
uint8_t application_cnt_; uint8_t application_cnt_;
}; };
...@@ -121,22 +124,35 @@ struct dummy_transport { ...@@ -121,22 +124,35 @@ struct dummy_transport {
using application_type = dummy_application; using application_type = dummy_application;
dummy_transport(std::shared_ptr<std::vector<byte>> buf) : buf_(buf) { dummy_transport(std::shared_ptr<buffer_type> buf) : buf_(std::move(buf)) {
// nop
} }
template <class IdType> template <class IdType>
void write_packet(span<const byte> header, span<const byte> payload, IdType) { void write_packet(IdType, span<buffer_type*> buffers) {
buf_->insert(buf_->end(), header.begin(), header.end()); for (auto buf : buffers)
buf_->insert(buf_->end(), payload.begin(), payload.end()); buf_->insert(buf_->end(), buf->begin(), buf->end());
}
transport_type& transport() {
return *this;
}
buffer_type next_header_buffer() {
return {};
}
buffer_type next_payload_buffer() {
return {};
} }
private: private:
std::shared_ptr<std::vector<byte>> buf_; std::shared_ptr<buffer_type> buf_;
}; };
struct testdata { struct testdata {
testdata(uint8_t worker_id, node_id id, ip_endpoint ep) testdata(uint8_t worker_id, node_id id, ip_endpoint ep)
: worker_id(worker_id), nid(id), ep(ep) { : worker_id(worker_id), nid(std::move(id)), ep(ep) {
// nop // nop
} }
...@@ -168,7 +184,7 @@ struct fixture : host_fixture { ...@@ -168,7 +184,7 @@ struct fixture : host_fixture {
ip_endpoint>; ip_endpoint>;
fixture() fixture()
: buf{std::make_shared<std::vector<byte>>()}, : buf{std::make_shared<buffer_type>()},
dispatcher{dummy_application_factory{buf}}, dispatcher{dummy_application_factory{buf}},
dummy{buf} { dummy{buf} {
add_new_workers(); add_new_workers();
...@@ -180,7 +196,7 @@ struct fixture : host_fixture { ...@@ -180,7 +196,7 @@ struct fixture : host_fixture {
actor_config cfg; actor_config cfg;
auto p = make_actor<dummy_actor, strong_actor_ptr>(aid, nid, &sys, cfg); auto p = make_actor<dummy_actor, strong_actor_ptr>(aid, nid, &sys, cfg);
auto test_span = as_bytes(make_span(hello_test)); auto test_span = as_bytes(make_span(hello_test));
std::vector<byte> payload(test_span.begin(), test_span.end()); buffer_type payload(test_span.begin(), test_span.end());
auto strong_actor = actor_cast<strong_actor_ptr>(p); auto strong_actor = actor_cast<strong_actor_ptr>(p);
mailbox_element::forwarding_stack stack; mailbox_element::forwarding_stack stack;
auto elem = make_mailbox_element(std::move(strong_actor), auto elem = make_mailbox_element(std::move(strong_actor),
...@@ -213,7 +229,7 @@ struct fixture : host_fixture { ...@@ -213,7 +229,7 @@ struct fixture : host_fixture {
actor_system_config cfg{}; actor_system_config cfg{};
actor_system sys{cfg}; actor_system sys{cfg};
std::shared_ptr<std::vector<byte>> buf; std::shared_ptr<buffer_type> buf;
dispatcher_type dispatcher; dispatcher_type dispatcher;
dummy_transport dummy; dummy_transport dummy;
......
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