Commit a7e3a939 authored by Joseph Noir's avatar Joseph Noir

Add message for io failures, some related cleanup

parent 5fe3b5f6
......@@ -49,6 +49,7 @@ set(LIBCAF_IO_SRCS
src/socket_guard.cpp
src/newb_tcp.cpp
src/newb_udp.cpp
src/newb.cpp
)
add_custom_target(libcaf_io)
......
This diff is collapsed.
......@@ -30,8 +30,11 @@
#include "caf/io/accept_handle.hpp"
#include "caf/io/datagram_handle.hpp"
#include "caf/io/connection_handle.hpp"
#include "caf/io/network/operation.hpp"
#include "caf/io/network/receive_buffer.hpp"
namespace caf {
namespace io {
......@@ -182,6 +185,17 @@ inspect(Inspector& f, datagram_servant_closed_msg& x) {
return f(meta::type_name("datagram_servant_closed_msg"), x.handles);
}
// Signals a read error to a newb.
struct io_error_msg {
caf::io::network::operation op;
error err;
};
template <class Inspector>
typename Inspector::result_type
inspect(Inspector& f, io_error_msg& x) {
return f(meta::type_name("io_error_msg"), x.op, x.err);
}
} // namespace io
} // namespace caf
......@@ -140,8 +140,6 @@ struct ordering {
}
error timeout(atom_value atm, uint32_t id) {
std::cout << "got timeout message" << std::endl;
std::abort();
if (atm == ordering_atom::value) {
error err = none;
sequence_type seq = static_cast<sequence_type>(id);
......
......@@ -27,19 +27,19 @@ namespace policy {
struct tcp_transport : public io::network::transport_policy {
tcp_transport();
error read_some(io::network::event_handler* parent) override;
io::network::rw_state read_some(io::network::newb_base* parent) override;
bool should_deliver() override;
void prepare_next_read(io::network::event_handler*) override;
void prepare_next_read(io::network::newb_base*) override;
void configure_read(io::receive_policy::config config) override;
error write_some(io::network::event_handler* parent) override;
io::network::rw_state write_some(io::network::newb_base* parent) override;
void prepare_next_write(io::network::event_handler* parent) override;
void prepare_next_write(io::network::newb_base* parent) override;
void flush(io::network::event_handler* parent) override;
void flush(io::network::newb_base* parent) override;
expected<io::network::native_socket>
connect(const std::string& host, uint16_t port,
......@@ -61,7 +61,7 @@ struct accept_tcp : public io::network::accept_policy {
create_socket(uint16_t port,const char* host,bool reuse = false) override;
std::pair<io::network::native_socket, io::network::transport_policy_ptr>
accept(io::network::event_handler* parent) override;
accept(io::network::newb_base* parent) override;
void init(io::network::newb_base& n) override;
};
......
......@@ -27,26 +27,26 @@ namespace policy {
struct udp_transport : public io::network::transport_policy {
udp_transport();
error read_some(io::network::event_handler* parent) override;
io::network::rw_state read_some(io::network::newb_base* parent) override;
inline bool should_deliver() override {
CAF_LOG_TRACE("");
return received_bytes != 0 && sender == endpoint;
}
void prepare_next_read(io::network::event_handler*) override;
void prepare_next_read(io::network::newb_base*) override;
inline void configure_read(io::receive_policy::config) override {
// nop
}
error write_some(io::network::event_handler* parent) override;
io::network::rw_state write_some(io::network::newb_base* parent) override;
void prepare_next_write(io::network::event_handler* parent) override;
void prepare_next_write(io::network::newb_base* parent) override;
io::network::byte_buffer& wr_buf() override;
void flush(io::network::event_handler* parent) override;
void flush(io::network::newb_base* parent) override;
expected<io::network::native_socket>
connect(const std::string& host, uint16_t port,
......@@ -73,7 +73,7 @@ struct accept_udp : public io::network::accept_policy {
create_socket(uint16_t port, const char* host, bool reuse = false) override;
std::pair<io::network::native_socket, io::network::transport_policy_ptr>
accept(io::network::event_handler*) override;
accept(io::network::newb_base*) override;
void init(io::network::newb_base& n) override;
};
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| 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/io/network/newb.hpp"
namespace caf {
namespace io {
namespace network {
// -- newb_base ----------------------------------------------------------------
newb_base::newb_base(default_multiplexer& dm, native_socket sockfd)
: event_handler(dm, sockfd) {
// nop
}
// -- transport_policy ---------------------------------------------------------
transport_policy::transport_policy()
: received_bytes{0},
max_consecutive_reads{50} {
// nop
}
transport_policy::~transport_policy() {
// nop
}
io::network::rw_state transport_policy::write_some(newb_base*) {
return io::network::rw_state::indeterminate;
}
io::network::rw_state transport_policy::read_some(newb_base*) {
return io::network::rw_state::indeterminate;
}
bool transport_policy::should_deliver() {
return true;
}
bool transport_policy::must_read_more(newb_base*) {
return false;
}
void transport_policy::prepare_next_read(newb_base*) {
// nop
}
void transport_policy::prepare_next_write(newb_base*) {
// nop
}
void transport_policy::configure_read(receive_policy::config) {
// nop
}
void transport_policy::flush(newb_base*) {
// nop
}
byte_buffer& transport_policy::wr_buf() {
return offline_buffer;
}
expected<native_socket>
transport_policy::connect(const std::string&, uint16_t,
optional<io::network::protocol::network>) {
return sec::bad_function_call;
}
// -- accept_policy ------------------------------------------------------------
accept_policy::~accept_policy() {
// nop
}
// -- protocol_policy_base -----------------------------------------------------
protocol_policy_base::~protocol_policy_base() {
// nop
}
} // namespace network
} // namespace io
} // namespace caf
......@@ -71,7 +71,7 @@ tcp_transport::tcp_transport()
// nop
}
error tcp_transport::read_some(io::network::event_handler* parent) {
io::network::rw_state tcp_transport::read_some(io::network::newb_base* parent) {
CAF_LOG_TRACE("");
size_t len = receive_buffer.size() - collected;
void* buf = receive_buffer.data() + collected;
......@@ -79,14 +79,14 @@ error tcp_transport::read_some(io::network::event_handler* parent) {
reinterpret_cast<io::network::socket_recv_ptr>(buf),
len, io::network::no_sigpipe_io_flag);
if (io::network::is_error(sres, true) || sres == 0) {
std::cerr << "read some error" << std::endl;
// recv returns 0 when the peer has performed an orderly shutdown
return sec::runtime_error;
// Recv returns 0 when the peer has performed an orderly shutdown.
CAF_LOG_DEBUG("recv failed" << CAF_ARG(sres));
return io::network::rw_state::failure;
}
size_t result = (sres > 0) ? static_cast<size_t>(sres) : 0;
collected += result;
received_bytes = collected;
return none;
return io::network::rw_state::success;
}
bool tcp_transport::should_deliver() {
......@@ -94,7 +94,7 @@ bool tcp_transport::should_deliver() {
return collected >= read_threshold;
}
void tcp_transport::prepare_next_read(io::network::event_handler*) {
void tcp_transport::prepare_next_read(io::network::newb_base*) {
collected = 0;
received_bytes = 0;
switch (rd_flag) {
......@@ -109,7 +109,7 @@ void tcp_transport::prepare_next_read(io::network::event_handler*) {
read_threshold = 1;
break;
case io::receive_policy_flag::at_least: {
// read up to 10% more, but at least allow 100 bytes more
// Read up to 10% more, but at least allow 100 bytes more.
auto maximumsize = maximum + std::max<size_t>(100, maximum / 10);
if (receive_buffer.size() != maximumsize)
receive_buffer.resize(maximumsize);
......@@ -124,25 +124,27 @@ void tcp_transport::configure_read(io::receive_policy::config config) {
maximum = config.second;
}
error tcp_transport::write_some(io::network::event_handler* parent) {
io::network::rw_state tcp_transport::write_some(io::network::newb_base* parent) {
CAF_LOG_TRACE("");
const void* buf = send_buffer.data() + written;
auto len = send_buffer.size() - written;
auto sres = ::send(parent->fd(),
reinterpret_cast<io::network::socket_send_ptr>(buf),
len, io::network::no_sigpipe_io_flag);
if (io::network::is_error(sres, true))
return sec::runtime_error;
if (io::network::is_error(sres, true)) {
CAF_LOG_ERROR("send failed"
<< CAF_ARG(io::network::last_socket_error_as_string()));
return io::network::rw_state::failure;
}
size_t result = (sres > 0) ? static_cast<size_t>(sres) : 0;
written += result;
count += 1;
auto remaining = send_buffer.size() - written;
if (remaining == 0)
prepare_next_write(parent);
return none;
return io::network::rw_state::success;
}
void tcp_transport::prepare_next_write(io::network::event_handler* parent) {
void tcp_transport::prepare_next_write(io::network::newb_base* parent) {
written = 0;
send_buffer.clear();
if (offline_buffer.empty()) {
......@@ -154,7 +156,7 @@ void tcp_transport::prepare_next_write(io::network::event_handler* parent) {
}
}
void tcp_transport::flush(io::network::event_handler* parent) {
void tcp_transport::flush(io::network::newb_base* parent) {
CAF_ASSERT(parent != nullptr);
CAF_LOG_TRACE(CAF_ARG(offline_buffer.size()));
if (!offline_buffer.empty() && !writing) {
......@@ -180,7 +182,7 @@ accept_tcp::create_socket(uint16_t port, const char* host, bool reuse) {
}
std::pair<io::network::native_socket, io::network::transport_policy_ptr>
accept_tcp::accept(io::network::event_handler* parent) {
accept_tcp::accept(io::network::newb_base* parent) {
using namespace io::network;
sockaddr_storage addr;
std::memset(&addr, 0, sizeof(addr));
......
......@@ -71,7 +71,7 @@ udp_transport::udp_transport()
// nop
}
error udp_transport::read_some(io::network::event_handler* parent) {
io::network::rw_state udp_transport::read_some(io::network::newb_base* parent) {
CAF_LOG_TRACE(CAF_ARG(parent->fd()));
memset(sender.address(), 0, sizeof(sockaddr_storage));
io::network::socket_size_type len = sizeof(sockaddr_storage);
......@@ -80,11 +80,8 @@ error udp_transport::read_some(io::network::event_handler* parent) {
auto sres = ::recvfrom(parent->fd(), buf_ptr, buf_len,
0, sender.address(), &len);
if (io::network::is_error(sres, true)) {
CAF_LOG_ERROR("recvfrom returned" << CAF_ARG(sres));
return sec::runtime_error;
} else if (io::network::would_block_or_temporarily_unavailable(
io::network::last_socket_error())) {
return sec::end_of_stream;
CAF_LOG_ERROR("recvfrom failed" << CAF_ARG(sres));
return io::network::rw_state::failure;
}
if (sres == 0)
CAF_LOG_INFO("Received empty datagram");
......@@ -97,15 +94,15 @@ error udp_transport::read_some(io::network::event_handler* parent) {
endpoint = sender;
first_message = false;
}
return none;
return io::network::rw_state::success;
}
void udp_transport::prepare_next_read(io::network::event_handler*) {
void udp_transport::prepare_next_read(io::network::newb_base*) {
received_bytes = 0;
receive_buffer.resize(maximum);
}
error udp_transport::write_some(io::network::event_handler* parent) {
io::network::rw_state udp_transport::write_some(io::network::newb_base* parent) {
using namespace caf::io::network;
CAF_LOG_TRACE(CAF_ARG(parent->fd()) << CAF_ARG(send_buffer.size()));
socket_size_type len = static_cast<socket_size_type>(*endpoint.clength());
......@@ -114,22 +111,24 @@ error udp_transport::write_some(io::network::event_handler* parent) {
auto sres = ::sendto(parent->fd(), buf_ptr, buf_len,
0, endpoint.caddress(), len);
if (is_error(sres, true)) {
std::cerr << "sento failed: " << last_socket_error_as_string() << std::endl;
std::abort();
CAF_LOG_ERROR("sendto returned" << CAF_ARG(sres));
return sec::runtime_error;
CAF_LOG_ERROR("sendto failed" << CAF_ARG(sres));
return io::network::rw_state::failure;
}
size_t sent_bytes = (sres > 0) ? static_cast<size_t>(sres) : 0;
// TODO: This only works if we always write send_sizes.front()
if (sent_bytes != buf_len) {
CAF_LOG_ERROR("failed to send complete datagram");
return io::network::rw_state::failure;
}
send_sizes.pop_front();
written += (sres > 0) ? static_cast<size_t>(sres) : 0;
written += sent_bytes;
auto remaining = send_buffer.size() - written;
count += 1;
if (remaining == 0)
prepare_next_write(parent);
return none;
return io::network::rw_state::success;
}
void udp_transport::prepare_next_write(io::network::event_handler* parent) {
void udp_transport::prepare_next_write(io::network::newb_base* parent) {
written = 0;
send_buffer.clear();
send_sizes.clear();
......@@ -157,7 +156,7 @@ io::network::byte_buffer& udp_transport::wr_buf() {
return offline_buffer;
}
void udp_transport::flush(io::network::event_handler* parent) {
void udp_transport::flush(io::network::newb_base* parent) {
CAF_ASSERT(parent != nullptr);
CAF_LOG_TRACE(CAF_ARG(offline_buffer.size()));
if (!offline_buffer.empty() && !writing) {
......@@ -187,7 +186,7 @@ accept_udp::create_socket(uint16_t port, const char* host, bool reuse) {
}
std::pair<io::network::native_socket, io::network::transport_policy_ptr>
accept_udp::accept(io::network::event_handler*) {
accept_udp::accept(io::network::newb_base*) {
auto res = io::network::new_local_udp_endpoint_impl(0, nullptr);
if (!res) {
CAF_LOG_DEBUG("failed to create local endpoint");
......
......@@ -300,7 +300,7 @@ struct accept_policy_impl : public network::accept_policy {
}
std::pair<native_socket, network::transport_policy_ptr>
accept(network::event_handler*) override {
accept(network::newb_base*) override {
// TODO: For UDP read the message into a buffer. Create a new socket.
// Move the buffer into the transport policy as the new receive buffer.
network::transport_policy_ptr ptr{new network::transport_policy};
......@@ -427,8 +427,7 @@ CAF_TEST(read event) {
bs(payload);
dummy.transport->received_bytes = buf.size();
CAF_MESSAGE("trigger a read event");
auto err = dummy.read_event();
CAF_REQUIRE(!err);
dummy.read_event();
CAF_MESSAGE("check the basp header and payload");
CAF_REQUIRE(!dummy.messages.empty());
auto& msg = dummy.messages.front().first;
......@@ -475,8 +474,7 @@ CAF_TEST(timeouts) {
CAF_MESSAGE("trigger read event");
auto& dummy = deref<dummy_basp_newb>(self);
dummy.transport->max_consecutive_reads = 1;
auto err = dummy.read_event();
CAF_REQUIRE(!err);
dummy.read_event();
CAF_CHECK(!dummy.expected.empty());
CAF_MESSAGE("trigger waiting timeouts");
// Trigger timeout.
......
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