Commit 068470bb authored by Dominik Charousset's avatar Dominik Charousset

Fix MinGW build

Fix some issues with CAF on MinGW:
- Correctly initialize networking on Windows using WSAStartup()
- Rename `interface` member function to `message_types` because `interface` is
  a define on Windows (srsly Microsoft?)
- Cast to correct pointer type when using `send` or `recv`
- Fix some warnings caused by using `int` instead of `native_socket_t`

  The issues have been reported by GitHub user xmt.
parent e1643bbb
...@@ -7,6 +7,13 @@ ...@@ -7,6 +7,13 @@
* - ./build/bin/broker -c localhost 4242 * * - ./build/bin/broker -c localhost 4242 *
\ ******************************************************************************/ \ ******************************************************************************/
#ifdef WIN32
# define _WIN32_WINNT 0x0600
# include <Winsock2.h>
#else
# include <arpa/inet.h> // htonl
#endif
#include <vector> #include <vector>
#include <string> #include <string>
#include <limits> #include <limits>
...@@ -15,12 +22,6 @@ ...@@ -15,12 +22,6 @@
#include <cassert> #include <cassert>
#include <iostream> #include <iostream>
#ifdef WIN32
#include <Winsock2.h>
#else
#include <arpa/inet.h> // htonl
#endif
#include "caf/all.hpp" #include "caf/all.hpp"
#include "caf/io/all.hpp" #include "caf/io/all.hpp"
......
...@@ -168,10 +168,10 @@ class abstract_actor : public abstract_channel { ...@@ -168,10 +168,10 @@ class abstract_actor : public abstract_channel {
} }
/** /**
* Returns the type interface as set of strings or an empty set * Returns the set of accepted messages types as strings or
* if this actor is untyped. * an empty set if this actor is untyped.
*/ */
virtual std::set<std::string> interface() const; virtual std::set<std::string> message_types() const;
protected: protected:
/** /**
......
...@@ -95,7 +95,11 @@ class actor_addr : detail::comparable<actor_addr>, ...@@ -95,7 +95,11 @@ class actor_addr : detail::comparable<actor_addr>,
*/ */
bool is_remote() const; bool is_remote() const;
std::set<std::string> interface() const; /**
* Returns the set of accepted messages types as strings or
* an empty set if this actor is untyped.
*/
std::set<std::string> message_types() const;
private: private:
......
...@@ -130,7 +130,7 @@ class typed_actor ...@@ -130,7 +130,7 @@ class typed_actor
return m_ptr ? 1 : 0; return m_ptr ? 1 : 0;
} }
static std::set<std::string> get_interface() { static std::set<std::string> get_message_types() {
return {detail::to_uniform_name<Rs>()...}; return {detail::to_uniform_name<Rs>()...};
} }
......
...@@ -38,9 +38,9 @@ namespace caf { ...@@ -38,9 +38,9 @@ namespace caf {
* @extends local_actor * @extends local_actor
*/ */
template <class... Rs> template <class... Rs>
class typed_event_based_actor class typed_event_based_actor : public
: public extend<local_actor, typed_event_based_actor<Rs...>>::template with< extend<local_actor, typed_event_based_actor<Rs...>>::template
mixin::mailbox_based, with<mixin::mailbox_based,
mixin::behavior_stack_based<typed_behavior<Rs...>>::template impl, mixin::behavior_stack_based<typed_behavior<Rs...>>::template impl,
mixin::sync_sender<nonblocking_response_handle_tag>::template impl> { mixin::sync_sender<nonblocking_response_handle_tag>::template impl> {
public: public:
...@@ -52,7 +52,7 @@ class typed_event_based_actor ...@@ -52,7 +52,7 @@ class typed_event_based_actor
using behavior_type = typed_behavior<Rs...>; using behavior_type = typed_behavior<Rs...>;
std::set<std::string> interface() const override { std::set<std::string> message_types() const override {
return {detail::to_uniform_name<Rs>()...}; return {detail::to_uniform_name<Rs>()...};
} }
......
...@@ -217,7 +217,7 @@ void abstract_actor::cleanup(uint32_t reason) { ...@@ -217,7 +217,7 @@ void abstract_actor::cleanup(uint32_t reason) {
} }
} }
std::set<std::string> abstract_actor::interface() const { std::set<std::string> abstract_actor::message_types() const {
// defaults to untyped // defaults to untyped
return std::set<std::string>{}; return std::set<std::string>{};
} }
......
...@@ -66,8 +66,8 @@ bool actor_addr::is_remote() const { ...@@ -66,8 +66,8 @@ bool actor_addr::is_remote() const {
return m_ptr ? m_ptr->is_remote() : false; return m_ptr ? m_ptr->is_remote() : false;
} }
std::set<std::string> actor_addr::interface() const { std::set<std::string> actor_addr::message_types() const {
return !m_ptr ? std::set<std::string>{} : m_ptr->interface(); return !m_ptr ? std::set<std::string>{} : m_ptr->message_types();
} }
} // namespace caf } // namespace caf
...@@ -172,7 +172,7 @@ std::vector<std::string> get_mac_addresses() { ...@@ -172,7 +172,7 @@ std::vector<std::string> get_mac_addresses() {
#include <iphlpapi.h> #include <iphlpapi.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "caf/singletons.hpp" #include "caf/detail/singletons.hpp"
namespace { namespace {
......
...@@ -63,39 +63,16 @@ ...@@ -63,39 +63,16 @@
# ifndef POLLRDHUP # ifndef POLLRDHUP
# define POLLRDHUP POLLHUP # define POLLRDHUP POLLHUP
# endif # endif
namespace caf {
namespace io {
namespace network {
constexpr short input_mask = POLLIN | POLLPRI;
constexpr short error_mask = POLLRDHUP | POLLERR | POLLHUP | POLLNVAL;
constexpr short output_mask = POLLOUT;
class event_handler;
using multiplexer_data = pollfd;
using multiplexer_poll_shadow_data = std::vector<event_handler*>;
} // namespace network
} // namespace io
} // namespace caf
#else #else
# define CAF_EPOLL_MULTIPLEXER # define CAF_EPOLL_MULTIPLEXER
# include <sys/epoll.h> # include <sys/epoll.h>
namespace caf {
namespace io {
namespace network {
constexpr int input_mask = EPOLLIN;
constexpr int error_mask = EPOLLRDHUP | EPOLLERR | EPOLLHUP;
constexpr int output_mask = EPOLLOUT;
using multiplexer_data = epoll_event;
using multiplexer_poll_shadow_data = int;
} // namespace network
} // namespace io
} // namespace caf
#endif #endif
namespace caf { namespace caf {
namespace io { namespace io {
namespace network { namespace network {
// some more annoying platform-dependent bootstrapping // annoying platform-dependent bootstrapping
#ifdef CAF_WINDOWS #ifdef CAF_WINDOWS
using native_socket_t = SOCKET; using native_socket_t = SOCKET;
using setsockopt_ptr = const char*; using setsockopt_ptr = const char*;
...@@ -124,6 +101,23 @@ namespace network { ...@@ -124,6 +101,23 @@ namespace network {
constexpr int ec_interrupted_syscall = EINTR; constexpr int ec_interrupted_syscall = EINTR;
#endif #endif
// poll vs epoll backend
#if !defined(CAF_LINUX) || defined(CAF_POLL_IMPL) // poll() multiplexer
constexpr short input_mask = POLLIN | POLLPRI;
constexpr short error_mask = POLLRDHUP | POLLERR | POLLHUP | POLLNVAL;
constexpr short output_mask = POLLOUT;
class event_handler;
using multiplexer_data = pollfd;
using multiplexer_poll_shadow_data = std::vector<event_handler*>;
#else
# define CAF_EPOLL_MULTIPLEXER
constexpr int input_mask = EPOLLIN;
constexpr int error_mask = EPOLLRDHUP | EPOLLERR | EPOLLHUP;
constexpr int output_mask = EPOLLOUT;
using multiplexer_data = epoll_event;
using multiplexer_poll_shadow_data = native_socket_t;
#endif
/** /**
* Platform-specific native socket type. * Platform-specific native socket type.
*/ */
...@@ -315,6 +309,9 @@ class multiplexer { ...@@ -315,6 +309,9 @@ class multiplexer {
private: private:
// platform-dependent additional initialization code
void init();
template <class F> template <class F>
void new_event(F fun, operation op, native_socket fd, event_handler* ptr) { void new_event(F fun, operation op, native_socket fd, event_handler* ptr) {
CAF_REQUIRE(fd != invalid_socket); CAF_REQUIRE(fd != invalid_socket);
......
...@@ -40,7 +40,7 @@ struct typed_remote_actor_helper<detail::type_list<Ts...>> { ...@@ -40,7 +40,7 @@ struct typed_remote_actor_helper<detail::type_list<Ts...>> {
using return_type = typed_actor<Ts...>; using return_type = typed_actor<Ts...>;
template <class... Vs> template <class... Vs>
return_type operator()(Vs&&... vs) { return_type operator()(Vs&&... vs) {
auto iface = return_type::get_interface(); auto iface = return_type::get_message_types();
auto tmp = remote_actor_impl(std::forward<Vs>(vs)..., std::move(iface)); auto tmp = remote_actor_impl(std::forward<Vs>(vs)..., std::move(iface));
return actor_cast<return_type>(tmp); return actor_cast<return_type>(tmp);
} }
......
...@@ -552,7 +552,7 @@ void basp_broker::init_handshake_as_sever(connection_context& ctx, ...@@ -552,7 +552,7 @@ void basp_broker::init_handshake_as_sever(connection_context& ctx,
{ // lifetime scope of first serializer { // lifetime scope of first serializer
binary_serializer bs1(std::back_inserter(buf), &m_namespace); binary_serializer bs1(std::back_inserter(buf), &m_namespace);
bs1 << addr.id(); bs1 << addr.id();
auto sigs = addr.interface(); auto sigs = addr.message_types();
bs1 << static_cast<uint32_t>(sigs.size()); bs1 << static_cast<uint32_t>(sigs.size());
for (auto& sig : sigs) for (auto& sig : sigs)
bs1 << sig; bs1 << sig;
......
...@@ -166,7 +166,7 @@ namespace network { ...@@ -166,7 +166,7 @@ namespace network {
a.inaddr.sin_port = 0; a.inaddr.sin_port = 0;
bool success = false; bool success = false;
// makes sure all sockets are closed in case of an error // makes sure all sockets are closed in case of an error
auto guard = util::make_scope_guard([&] { auto guard = detail::make_scope_guard([&] {
if (success) { if (success) {
return; // everyhting's fine return; // everyhting's fine
} }
...@@ -219,6 +219,7 @@ namespace network { ...@@ -219,6 +219,7 @@ namespace network {
// registered to epoll. // registered to epoll.
multiplexer::multiplexer() : m_epollfd(invalid_socket), m_shadow(1) { multiplexer::multiplexer() : m_epollfd(invalid_socket), m_shadow(1) {
init();
m_epollfd = epoll_create1(EPOLL_CLOEXEC); m_epollfd = epoll_create1(EPOLL_CLOEXEC);
if (m_epollfd == -1) { if (m_epollfd == -1) {
CAF_LOG_ERROR("epoll_create1: " << strerror(errno)); CAF_LOG_ERROR("epoll_create1: " << strerror(errno));
...@@ -333,6 +334,7 @@ namespace network { ...@@ -333,6 +334,7 @@ namespace network {
// i.e., O(1), access the actual object when handling socket events. // i.e., O(1), access the actual object when handling socket events.
multiplexer::multiplexer() : m_epollfd(-1) { multiplexer::multiplexer() : m_epollfd(-1) {
init();
// initial setup // initial setup
m_pipe = create_pipe(); m_pipe = create_pipe();
pollfd pipefd; pollfd pipefd;
...@@ -351,7 +353,7 @@ namespace network { ...@@ -351,7 +353,7 @@ namespace network {
// altering the pollset while traversing it is not exactly a // altering the pollset while traversing it is not exactly a
// bright idea ... // bright idea ...
struct fd_event { struct fd_event {
int fd; // our file descriptor native_socket_t fd; // our file descriptor
short mask; // the event mask returned by poll() short mask; // the event mask returned by poll()
short fd_mask; // the mask associated with fd short fd_mask; // the mask associated with fd
event_handler* ptr; // nullptr in case of a pipe event event_handler* ptr; // nullptr in case of a pipe event
...@@ -394,8 +396,7 @@ namespace network { ...@@ -394,8 +396,7 @@ namespace network {
if (pfd.revents != 0) { if (pfd.revents != 0) {
CAF_LOG_DEBUG("event on socket " << pfd.fd CAF_LOG_DEBUG("event on socket " << pfd.fd
<< ", revents = " << pfd.revents); << ", revents = " << pfd.revents);
poll_res.push_back({pfd.fd, pfd.revents, poll_res.push_back({pfd.fd, pfd.revents, pfd.events, m_shadow[i]});
pfd.events, m_shadow[i]});
pfd.revents = 0; pfd.revents = 0;
--presult; // stop as early as possible --presult; // stop as early as possible
} }
...@@ -534,7 +535,8 @@ void multiplexer::wr_dispatch_request(runnable* ptr) { ...@@ -534,7 +535,8 @@ void multiplexer::wr_dispatch_request(runnable* ptr) {
intptr_t ptrval = reinterpret_cast<intptr_t>(ptr); intptr_t ptrval = reinterpret_cast<intptr_t>(ptr);
// on windows, we actually have sockets, otherwise we have file handles // on windows, we actually have sockets, otherwise we have file handles
# ifdef CAF_WINDOWS # ifdef CAF_WINDOWS
::send(m_pipe.second, &ptrval, sizeof(ptrval), 0); ::send(m_pipe.second, reinterpret_cast<socket_send_ptr>(&ptrval),
sizeof(ptrval), 0);
# else # else
::write(m_pipe.second, &ptrval, sizeof(ptrval)); ::write(m_pipe.second, &ptrval, sizeof(ptrval));
# endif # endif
...@@ -544,7 +546,8 @@ multiplexer::runnable* multiplexer::rd_dispatch_request() { ...@@ -544,7 +546,8 @@ multiplexer::runnable* multiplexer::rd_dispatch_request() {
intptr_t ptrval; intptr_t ptrval;
// on windows, we actually have sockets, otherwise we have file handles // on windows, we actually have sockets, otherwise we have file handles
# ifdef CAF_WINDOWS # ifdef CAF_WINDOWS
::recv(m_pipe.first, &ptrval, sizeof(ptrval), 0); ::recv(m_pipe.first, reinterpret_cast<socket_recv_ptr>(&ptrval),
sizeof(ptrval), 0);
# else # else
::read(m_pipe.first, &ptrval, sizeof(ptrval)); ::read(m_pipe.first, &ptrval, sizeof(ptrval));
# endif # endif
...@@ -604,8 +607,20 @@ void multiplexer::handle_socket_event(native_socket fd, int mask, ...@@ -604,8 +607,20 @@ void multiplexer::handle_socket_event(native_socket fd, int mask,
} }
} }
void multiplexer::init() {
# ifdef CAF_WINDOWS
WSADATA WinsockData;
if (WSAStartup(MAKEWORD(2, 2), &WinsockData) != 0) {
CAF_CRITICAL("WSAStartup failed");
}
# endif
}
multiplexer::~multiplexer() { multiplexer::~multiplexer() {
if (m_epollfd != -1) { # ifdef CAF_WINDOWS
WSACleanup();
# endif
if (m_epollfd != invalid_socket) {
closesocket(m_epollfd); closesocket(m_epollfd);
} }
closesocket(m_pipe.first); closesocket(m_pipe.first);
......
...@@ -178,7 +178,7 @@ void test_event_testee() { ...@@ -178,7 +178,7 @@ void test_event_testee() {
"caf::replies_to<@str>::with<void>", "caf::replies_to<@str>::with<void>",
"caf::replies_to<float>::with<void>", "caf::replies_to<float>::with<void>",
"caf::replies_to<@i32>::with<@i32>"}; "caf::replies_to<@i32>::with<@i32>"};
CAF_CHECK_EQUAL(join(sub_et->interface(), ","), join(iface, ",")); CAF_CHECK_EQUAL(join(sub_et->message_types(), ","), join(iface, ","));
self->send(sub_et, get_state_msg{}); self->send(sub_et, get_state_msg{});
// we expect three 42s // we expect three 42s
int i = 0; int i = 0;
...@@ -224,10 +224,11 @@ string_actor::behavior_type simple_string_reverter() { ...@@ -224,10 +224,11 @@ string_actor::behavior_type simple_string_reverter() {
void test_simple_string_reverter() { void test_simple_string_reverter() {
scoped_actor self; scoped_actor self;
// actor-under-test // actor-under-test
auto aut = self->spawn_typed<monitored>( auto aut = self->spawn_typed<monitored>(simple_relay,
simple_relay, spawn_typed(simple_string_reverter), true); spawn_typed(simple_string_reverter),
true);
set<string> iface{"caf::replies_to<@str>::with<@str>"}; set<string> iface{"caf::replies_to<@str>::with<@str>"};
CAF_CHECK(aut->interface() == iface); CAF_CHECK(aut->message_types() == iface);
self->sync_send(aut, "Hello World!").await([](const string& answer) { self->sync_send(aut, "Hello World!").await([](const string& answer) {
CAF_CHECK_EQUAL(answer, "!dlroW olleH"); CAF_CHECK_EQUAL(answer, "!dlroW olleH");
}); });
......
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