From 46dd23a93e61c39df2b2f94135f54328fbe0e358 Mon Sep 17 00:00:00 2001 From: Lucas Lazare Date: Tue, 6 Nov 2018 18:07:16 -0500 Subject: [PATCH 01/10] Updating logging No longer static (that was a bad idea, as levels were shared) Wait, there's a develop branch, too ! --- include/breep/network/basic_network.hpp | 52 ++-- include/breep/network/basic_peer_manager.hpp | 8 +- .../breep/network/detail/object_builder.hpp | 44 +-- include/breep/network/detail/utils.hpp | 39 ++- .../breep/network/impl/basic_peer_manager.tcc | 140 ++++----- include/breep/network/impl/local_peer.tcc | 14 +- include/breep/network/local_peer.hpp | 4 +- .../breep/network/tcp/basic_io_manager.hpp | 10 +- .../network/tcp/impl/basic_io_manager.tcc | 32 +- include/breep/util/logger.hpp | 283 ++++++++++-------- include/breep/util/type_traits.hpp | 11 +- 11 files changed, 353 insertions(+), 284 deletions(-) diff --git a/include/breep/network/basic_network.hpp b/include/breep/network/basic_network.hpp index b3ab468..1176963 100644 --- a/include/breep/network/basic_network.hpp +++ b/include/breep/network/basic_network.hpp @@ -192,7 +192,7 @@ namespace breep { breep::serializer s; s << type_traits::hash_code(); s << data; - breep::logger.debug("Sending " + type_traits::universal_name()); + m_log.debug("Sending " + type_traits::universal_name()); m_manager.send_to_all(s.str()); } @@ -214,7 +214,7 @@ namespace breep { breep::serializer s; s << type_traits::hash_code(); s << data; - breep::logger.debug("Sending private " + type_traits::universal_name() + " to " + p.id_as_string()); + m_log.debug("Sending private " + type_traits::universal_name() + " to " + p.id_as_string()); m_manager.send_to(p, s.str()); } @@ -234,11 +234,11 @@ namespace breep { auto associated_listener = m_data_listeners.find(breep::type_traits::hash_code()); if (associated_listener != m_data_listeners.end()) { auto ob = detail::any_cast*>(std::get(associated_listener->second)); - breep::logger.debug("Self sending " + breep::type_traits::universal_name() + "."); + m_log.debug("Self sending " + breep::type_traits::universal_name() + "."); ob->flush_listeners(); ob->fire(breep::basic_netdata_wrapper(*this, m_manager.self(), data, is_private)); } else { - breep::logger.warning("Unregistered type self-sent: " + breep::type_traits::universal_name()); + m_log.warning("Unregistered type self-sent: " + breep::type_traits::universal_name()); } } @@ -252,7 +252,7 @@ namespace breep { * @since 1.0.0 */ void send_packet(const packet& pack) const { - breep::logger.debug("Sending a packet"); + m_log.debug("Sending a packet"); m_manager.send_to_all(pack.m_s.str()); } @@ -267,7 +267,7 @@ namespace breep { * @since 1.0.0 */ void send_packet_to(const peer& target, const packet& pack) const { - breep::logger.debug("Sending a private packet"); + m_log.debug("Sending a private packet"); m_manager.send_to(target, pack.m_s.str()); } @@ -374,7 +374,7 @@ namespace breep { */ listener_id add_connection_listener(connection_listener listener) { std::lock_guard lock_guard(m_connection_mutex); - breep::logger.debug("Adding connection listener (id: " + std::to_string(m_id_count) + ")"); + m_log.debug("Adding connection listener (id: " + std::to_string(m_id_count) + ")"); m_co_listeners.emplace(m_id_count, listener); return m_id_count++; } @@ -396,7 +396,7 @@ namespace breep { */ listener_id add_disconnection_listener(disconnection_listener listener) { std::lock_guard lock_guard(m_disconnection_mutex); - breep::logger.debug("Adding disconnection listener (id: " + std::to_string(m_id_count) + ")"); + m_log.debug("Adding disconnection listener (id: " + std::to_string(m_id_count) + ")"); m_dc_listeners.emplace(m_id_count, listener); return m_id_count++; } @@ -413,7 +413,7 @@ namespace breep { */ bool remove_connection_listener(listener_id id) { std::lock_guard lock_guard(m_connection_mutex); - breep::logger.debug("Removing connection listener (id: " + std::to_string(m_id_count) + ")"); + m_log.debug("Removing connection listener (id: " + std::to_string(m_id_count) + ")"); return m_co_listeners.erase(id) > 0; } @@ -429,7 +429,7 @@ namespace breep { */ bool remove_disconnection_listener(listener_id id) { std::lock_guard lock_guard(m_disconnection_mutex); - breep::logger.debug("Removing disconnection listener (id: " + std::to_string(m_id_count) + ")"); + m_log.debug("Removing disconnection listener (id: " + std::to_string(m_id_count) + ")"); return m_dc_listeners.erase(id) > 0; } @@ -502,10 +502,10 @@ namespace breep { auto associated_listener = m_data_listeners.find(type_traits::hash_code()); if (associated_listener == m_data_listeners.end()) { std::lock_guard lock_guard(m_object_builder_mutex); - breep::logger.debug("New type being registered for listening: " + type_traits::universal_name()); + m_log.debug("New type being registered for listening: " + type_traits::universal_name()); std::shared_ptr> builder_ptr = std::make_shared>(); m_data_listeners.emplace(type_traits::hash_code(), detail::make_obj_tuple(builder_ptr)); - builder_ptr->set_log_level(logger.level()); + builder_ptr->set_log_level(m_log.level()); return builder_ptr->add_listener(m_id_count++, listener); } else { auto builder_ptr = detail::any_cast*>(std::get(associated_listener->second)); @@ -531,7 +531,7 @@ namespace breep { bool remove_data_listener(listener_id id) { auto associated_listener = m_data_listeners.find(type_traits::hash_code()); if (associated_listener == m_data_listeners.end()) { - breep::logger.warning + m_log.warning ("Trying to remove a listener of type " + type_traits::universal_name() + " that was not registered. (listener id: " + std::to_string(id) + ")"); return false; } else { @@ -558,7 +558,7 @@ namespace breep { bool remove_data_listener(const type_listener_id& id) { auto associated_listener = m_data_listeners.find(id.type_hash()); if (associated_listener == m_data_listeners.end()) { - breep::logger.warning + m_log.warning ("Trying to remove a listener for an unknown type (hash: " + std::to_string(id.type_hash()) + ") that was not registered. (listener id: " + std::to_string(id.id()) + ")"); return false; @@ -583,7 +583,7 @@ namespace breep { * @since 0.1.0 */ void set_log_level(log_level ll) const { - breep::logger.level(ll); + m_log.level(ll); m_manager.set_log_level(ll); for (auto& pair : m_data_listeners) { std::get(pair.second)(ll); @@ -601,7 +601,7 @@ namespace breep { if (object_builder != m_data_listeners.end()) { detail::any_cast*>(std::get(object_builder->second))->clear_any(); } else { - breep::logger.warning("Trying to clean an listener list for a type that was not registered (" + type_traits::universal_name() + ")"); + m_log.warning("Trying to clean an listener list for a type that was not registered (" + type_traits::universal_name() + ")"); } } @@ -613,7 +613,7 @@ namespace breep { * @since 0.1.0 */ void clear_any() { - breep::logger.debug("Cleaning any listeners"); + m_log.debug("Cleaning any listeners"); m_connection_mutex.lock(); m_co_listeners.clear(); @@ -674,7 +674,7 @@ namespace breep { breep::deserializer d(std::basic_string(data, data + data_size - sizeof(uint64_t))); if (hash_code == type_traits::hash_code()) { - breep::logger.trace("Received a packet. Unwrapping it."); + m_log.trace("Received a packet. Unwrapping it."); while(!d.empty()) { d >> hash_code; class_received(hash_code, source, d, sent_to_all); @@ -689,29 +689,29 @@ namespace breep { auto associated_listener = m_data_listeners.find(hash_code); if (associated_listener != m_data_listeners.end()) { if (!std::get(associated_listener->second)(*this, source, d, sent_to_all) && m_unlistened_listener) { - breep::logger.warning("Calling default listener."); + m_log.warning("Calling default listener."); m_unlistened_listener(*this, source, d, sent_to_all, hash_code); } m_object_builder_mutex.unlock(); } else if (m_unlistened_listener){ m_object_builder_mutex.unlock(); - breep::logger.warning("Unregistered type received: " + std::to_string(hash_code) + ". Calling default listener."); + m_log.warning("Unregistered type received: " + std::to_string(hash_code) + ". Calling default listener."); try { m_unlistened_listener(*this, source, d, sent_to_all, hash_code); } catch (const std::exception& e) { - breep::logger.warning("Exception thrown while calling default data listener"); - breep::logger.warning(e.what()); + m_log.warning("Exception thrown while calling default data listener"); + m_log.warning(e.what()); } catch (const std::exception* e) { - breep::logger.warning("Exception thrown while calling default data listener"); - breep::logger.warning(e->what()); + m_log.warning("Exception thrown while calling default data listener"); + m_log.warning(e->what()); delete e; } } else { m_object_builder_mutex.unlock(); - breep::logger.warning("Unregistered type received: " + std::to_string(hash_code)); + m_log.warning("Unregistered type received: " + std::to_string(hash_code)); } } @@ -728,6 +728,8 @@ namespace breep { std::mutex m_connection_mutex; std::mutex m_disconnection_mutex; std::mutex m_object_builder_mutex; + + mutable breep::logger m_log{logger::from_class()}; }; template diff --git a/include/breep/network/basic_peer_manager.hpp b/include/breep/network/basic_peer_manager.hpp index 0fd8818..ad1a29a 100644 --- a/include/breep/network/basic_peer_manager.hpp +++ b/include/breep/network/basic_peer_manager.hpp @@ -353,7 +353,7 @@ namespace breep { } void set_log_level(log_level ll) const { - breep::logger.level(ll); + m_log.level(ll); m_manager.set_log_level(ll); } @@ -474,11 +474,11 @@ namespace breep { void peers_list_handler(const peer& source, const std::vector& data); void peer_disconnection_handler(const peer& source, const std::vector& data); void empty_handler(const peer&, const std::vector&) { - breep::logger.warning("Call to empty_handler was made. This is not supposed to happen in normal circonstances.\n"); + m_log.warning("Call to empty_handler was made. This is not supposed to happen in normal circonstances.\n"); } void keep_alive_handler(const peer& p, const std::vector& /* unused */) { - breep::logger.trace("Received keep_alive from " + p.id_as_string()); + m_log.trace("Received keep_alive from " + p.id_as_string()); } std::unordered_map> m_peers; @@ -511,6 +511,8 @@ namespace breep { friend class detail::peer_manager_attorney; std::unique_ptr m_thread; + + mutable breep::logger m_log{logger::from_class()}; }; diff --git a/include/breep/network/detail/object_builder.hpp b/include/breep/network/detail/object_builder.hpp index da3b260..2833ad6 100644 --- a/include/breep/network/detail/object_builder.hpp +++ b/include/breep/network/detail/object_builder.hpp @@ -58,30 +58,30 @@ namespace breep { namespace detail { bool build_and_call(network& lnetwork, const typename network::peer& received_from, breep::deserializer& data, bool is_private) { if (is_private) { - breep::logger>.info("Received " + type_traits::universal_name()); + m_log.info("Received " + type_traits::universal_name()); } else { - breep::logger>.info("Received private " + type_traits::universal_name() + " from " + received_from.id_as_string()); + m_log.info("Received private " + type_traits::universal_name() + " from " + received_from.id_as_string()); } flush_listeners(); if (m_listeners.empty()) { - breep::logger>.debug("No listener for received " + type_traits::universal_name()); + m_log.debug("No listener for received " + type_traits::universal_name()); return false; } else { - breep::logger>.debug("Building object of type " + type_traits::universal_name()); + m_log.debug("Building object of type " + type_traits::universal_name()); try { T object; data >> object; fire(breep::basic_netdata_wrapper(lnetwork, received_from, object, is_private)); } catch (const std::exception& e) { - breep::logger>.warning("Exception thrown while deserializing object of type " + type_traits::universal_name()); - breep::logger>.warning(e.what()); + m_log.warning("Exception thrown while deserializing object of type " + type_traits::universal_name()); + m_log.warning(e.what()); return false; } catch (const std::exception* e) { - breep::logger>.warning("Exception thrown while deserializing object of type " + type_traits::universal_name()); - breep::logger>.warning(e->what()); + m_log.warning("Exception thrown while deserializing object of type " + type_traits::universal_name()); + m_log.warning(e->what()); delete e; return false; } @@ -93,7 +93,7 @@ namespace breep { namespace detail { type_listener_id add_listener(listener_id id, data_received_listener l) { std::lock_guard lock_guard(m_mutex); - breep::logger>.debug + m_log.debug ("Adding listener for type " + type_traits::universal_name () + ". (id: " + std::to_string(id) + ")"); m_to_add.push_back(std::pair>(id, l)); return type_listener_id(id, type_traits::hash_code()); @@ -103,7 +103,7 @@ namespace breep { namespace detail { std::lock_guard lock_guard(m_mutex); if (m_listeners.count(id)) { if (std::find_if(m_to_remove.cbegin(), m_to_remove.cend(), [id](auto l_id) -> bool { return l_id == id; }) == m_to_remove.cend()) { - breep::logger>.debug + m_log.debug ("Removing listener for type " + type_traits::universal_name () + ". (id: " + std::to_string(id) + ")"); m_to_remove.push_back(id); return true; @@ -111,25 +111,25 @@ namespace breep { namespace detail { } else { auto it = std::find_if(m_to_add.begin(), m_to_add.end(), [id](auto l_it) -> bool { return l_it.first == id; }); if (it != m_to_add.cend()) { - breep::logger>.debug + m_log.debug ("Removing listener for type " + type_traits::universal_name () + ". (id: " + std::to_string(id) + ")"); *it = m_to_add.back(); m_to_add.pop_back(); return true; } } - breep::logger>.debug + m_log.debug ("Listener with id " + std::to_string(id) + " not found when trying to remove from listeners of type " + type_traits::universal_name()); return false; } void set_log_level(log_level ll) { - breep::logger>.level(ll); + m_log.level(ll); } void clear_any() { std::lock_guard lock_guard(m_mutex); - breep::logger>.debug("Cleaning listeners list for type " + type_traits::universal_name()); + m_log.debug("Cleaning listeners list for type " + type_traits::universal_name()); m_listeners.clear(); m_to_add.clear(); m_to_remove.clear(); @@ -137,19 +137,19 @@ namespace breep { namespace detail { void fire(basic_netdata_wrapper&& wrapper) { for (auto& listeners_pair : m_listeners) { - breep::logger>.debug("Calling listener with id " + std::to_string(listeners_pair.first)); + m_log.debug("Calling listener with id " + std::to_string(listeners_pair.first)); wrapper.listener_id = listeners_pair.first; try { listeners_pair.second(wrapper); } catch (const std::exception& e) { - breep::logger>.warning("Exception thrown while calling listener " + m_log.warning("Exception thrown while calling listener " + std::to_string(wrapper.listener_id) + " for type " + type_traits::universal_name()); - breep::logger>.warning(e.what()); + m_log.warning(e.what()); } catch (const std::exception* e) { - breep::logger>.warning("Exception thrown while calling listener " + m_log.warning("Exception thrown while calling listener " + std::to_string(wrapper.listener_id) + " for type " + type_traits::universal_name()); - breep::logger>.warning(e->what()); + m_log.warning(e->what()); delete e; } } @@ -158,17 +158,19 @@ namespace breep { namespace detail { void flush_listeners() { std::lock_guard lock_guard(m_mutex); for (auto& pair : m_to_add) { - breep::logger>.trace("Effectively adding listener (id: " + std::to_string(pair.first) + ")"); + m_log.trace("Effectively adding listener (id: " + std::to_string(pair.first) + ")"); m_listeners.emplace(std::move(pair)); } for (auto& id : m_to_remove) { - breep::logger>.trace("Effectively removing listener (id: " + std::to_string(id) + ")"); + m_log.trace("Effectively removing listener (id: " + std::to_string(id) + ")"); m_listeners.erase(id); } } private: + breep::logger m_log{logger::from_class>()}; + std::unordered_map> m_listeners{}; std::vector>> m_to_add{}; std::vector m_to_remove{}; diff --git a/include/breep/network/detail/utils.hpp b/include/breep/network/detail/utils.hpp index e549140..140f516 100644 --- a/include/breep/network/detail/utils.hpp +++ b/include/breep/network/detail/utils.hpp @@ -3,7 +3,7 @@ /////////////////////////////////////////////////////////////////////////////////////////////////// // // -// Copyright 2017 Lucas Lazare. // +// Copyright 2017-2018 Lucas Lazare. // // This file is part of Breep project which is released under the // // European Union Public License v1.1. If a copy of the EUPL was // // not distributed with this software, you can obtain one at : // @@ -22,20 +22,53 @@ #include #include #include + +#if __cplusplus >= 201703L +#include +#include +#else #include #include +#endif namespace breep { namespace detail { +#if __cplusplus >= 201703L + template + using optional = std::optional; + + using any = std::any; + template + decltype(auto) any_cast(any& lany) { + return std::any_cast(lany); + } + template + decltype(auto) any_cast(const any& lany) { + return std::any_cast(lany); + } + template + decltype(auto) any_cast(any&& lany) { + return std::any_cast(std::move(lany)); + } + +#else template using optional = boost::optional; using any = boost::any; - template - auto any_cast(any& lany) { + decltype(auto) any_cast(any& lany) { + return boost::any_cast(lany); + } + template + decltype(auto) any_cast(const any& lany) { return boost::any_cast(lany); } + template + decltype(auto) any_cast(any&& lany) { + return boost::any_cast(std::move(lany)); + } +#endif struct unowning_linear_container; diff --git a/include/breep/network/impl/basic_peer_manager.tcc b/include/breep/network/impl/basic_peer_manager.tcc index b6fc730..f37338e 100644 --- a/include/breep/network/impl/basic_peer_manager.tcc +++ b/include/breep/network/impl/basic_peer_manager.tcc @@ -74,13 +74,13 @@ inline void breep::basic_peer_manager::send_to_all(const data_container& data std::vector sendable_data; detail::make_little_endian(data, sendable_data); - breep::logger.debug("Sending " + std::to_string(sendable_data.size()) + " octets"); + m_log.debug("Sending " + std::to_string(sendable_data.size()) + " octets"); for (const std::pair& pair : m_peers) { if (pair.second.distance() == 0) { - breep::logger.trace("Sending to " + pair.second.id_as_string()); + m_log.trace("Sending to " + pair.second.id_as_string()); m_manager.send(commands::send_to_all, sendable_data, pair.second); } else { - breep::logger.trace + m_log.trace ("Expecting another peer to forward to " + pair.second.id_as_string() + " (no direct connection)"); } } @@ -100,11 +100,11 @@ inline void breep::basic_peer_manager::send_to(const peer& p, const data_cont std::vector sendable_data; detail::make_little_endian(processed_data, sendable_data); - breep::logger.debug("Sending private data to " + p.id_as_string()); - breep::logger.debug("(" + std::to_string(data.size()) + " octets)"); + m_log.debug("Sending private data to " + p.id_as_string()); + m_log.debug("(" + std::to_string(data.size()) + " octets)"); if (p.distance() != 0) { - breep::logger.trace("Passing through " + m_me.path_to(p)->id_as_string() + " (no direct connection)"); + m_log.trace("Passing through " + m_me.path_to(p)->id_as_string() + " (no direct connection)"); } m_manager.send(commands::send_to, sendable_data, *m_me.path_to(p)); @@ -123,7 +123,7 @@ inline void breep::basic_peer_manager::run() { template inline void breep::basic_peer_manager::sync_run() { require_non_running(); - breep::logger.info("Starting the network."); + m_log.info("Starting the network."); m_running = true; m_waitfor_run.unlock(); m_manager.run(); @@ -152,7 +152,7 @@ inline bool breep::basic_peer_manager::sync_connect(const boost::asio::ip::ad template void breep::basic_peer_manager::disconnect() { - breep::logger.info("Shutting the network off."); + m_log.info("Shutting the network off."); m_manager.disconnect(); for (auto&& peer_pair : m_peers) { @@ -160,20 +160,20 @@ void breep::basic_peer_manager::disconnect() { m_manager.disconnect(p); p.distance(std::numeric_limits::max()); - breep::logger.info("Peer " + p.id_as_string() + " disconnected"); + m_log.info("Peer " + p.id_as_string() + " disconnected"); std::lock_guard lock_guard(m_dc_mutex); for(auto& l : m_dc_listener) { try { - breep::logger.trace("Calling disconnection listener (id: " + std::to_string(l.first) + ")"); + m_log.trace("Calling disconnection listener (id: " + std::to_string(l.first) + ")"); l.second(*this, p); } catch (const std::exception& e) { - breep::logger.warning("Exception thrown while calling disconnection listener " + l.first); - breep::logger.warning(e.what()); + m_log.warning("Exception thrown while calling disconnection listener " + l.first); + m_log.warning(e.what()); } catch (const std::exception* e) { - breep::logger.warning("Exception thrown while calling disconnection listener " + l.first); - breep::logger.warning(e->what()); + m_log.warning("Exception thrown while calling disconnection listener " + l.first); + m_log.warning(e->what()); delete e; } } @@ -189,7 +189,7 @@ template inline breep::listener_id breep::basic_peer_manager::add_connection_listener(connection_listener listener) { std::lock_guard lock_guard(m_co_mutex); m_co_listener.emplace(m_id_count, listener); - breep::logger.trace("Adding connection listener (id: " + std::to_string(m_id_count) + ")"); + m_log.trace("Adding connection listener (id: " + std::to_string(m_id_count) + ")"); return m_id_count++; } @@ -197,7 +197,7 @@ template inline breep::listener_id breep::basic_peer_manager::add_data_listener(data_received_listener listener){ std::lock_guard lock_guard(m_data_mutex); m_data_r_listener.emplace(m_id_count, listener); - breep::logger.trace("Adding data listener (id: " + std::to_string(m_id_count) + ")"); + m_log.trace("Adding data listener (id: " + std::to_string(m_id_count) + ")"); return m_id_count++; } @@ -205,28 +205,28 @@ template inline breep::listener_id breep::basic_peer_manager::add_disconnection_listener(disconnection_listener listener){ std::lock_guard lock_guard(m_dc_mutex); m_dc_listener.emplace(m_id_count, listener); - breep::logger.trace("Adding disconnection listener (id: " + std::to_string(m_id_count) + ")"); + m_log.trace("Adding disconnection listener (id: " + std::to_string(m_id_count) + ")"); return m_id_count++; } template inline bool breep::basic_peer_manager::remove_connection_listener(listener_id id) { std::lock_guard lock_guard(m_co_mutex); - breep::logger.trace("Removing connection listener (id: " + std::to_string(m_id_count) + ")"); + m_log.trace("Removing connection listener (id: " + std::to_string(m_id_count) + ")"); return m_co_listener.erase(id) > 0; } template inline bool breep::basic_peer_manager::remove_disconnection_listener(listener_id id) { std::lock_guard lock_guard(m_dc_mutex); - breep::logger.trace("Removing disconnection listener (id: " + std::to_string(m_id_count) + ")"); + m_log.trace("Removing disconnection listener (id: " + std::to_string(m_id_count) + ")"); return m_dc_listener.erase(id) > 0; } template inline bool breep::basic_peer_manager::remove_data_listener(listener_id id) { std::lock_guard lock_guard(m_data_mutex); - breep::logger.trace("Removing data listener (id: " + std::to_string(m_id_count) + ")"); + m_log.trace("Removing data listener (id: " + std::to_string(m_id_count) + ")"); return m_data_r_listener.erase(id) > 0; } @@ -241,18 +241,18 @@ bool breep::basic_peer_manager::try_connect(const boost::asio::ip::address& a require_non_running(); detail::optional new_peer(m_manager.connect(address, port_)); if (new_peer) { - breep::logger.info + m_log.info ("Successfully connected to " + new_peer->id_as_string() + "@" + address.to_string() + ":" + std::to_string(port_)); boost::uuids::uuid uuid = new_peer->id(); m_ignore_predicate = true; - peer_connected(std::move(new_peer.get())); + peer_connected(std::move(*new_peer)); m_ignore_predicate = false; m_manager.send(commands::retrieve_peers, constant::unused_param, m_peers.at(uuid)); return true; } else { - breep::logger.warning + m_log.warning ("Connection to [" + address.to_string() + "]:" + std::to_string(port_) + " failed"); m_manager.disconnect(); return false; @@ -262,7 +262,7 @@ bool breep::basic_peer_manager::try_connect(const boost::asio::ip::address& a template inline void breep::basic_peer_manager::peer_connected(peer&& p) { if (m_peers.count(p.id())) { - breep::logger.warning("Peer with id " + p.id_as_string() + m_log.warning("Peer with id " + p.id_as_string() + " tried to connect, but a peer with equal id is already connected."); m_manager.process_connection_denial(p); return; @@ -283,25 +283,25 @@ inline void breep::basic_peer_manager::peer_connected(peer&& p) { new_peer.distance(0); m_manager.process_connected_peer(new_peer); - breep::logger.info("Peer " + boost::uuids::to_string(id) + " connected"); + m_log.info("Peer " + boost::uuids::to_string(id) + " connected"); std::lock_guard lock_guard(m_co_mutex); for(auto& l : m_co_listener) { try { - breep::logger.trace("Calling connection listener (id: " + std::to_string(l.first) + ")"); + m_log.trace("Calling connection listener (id: " + std::to_string(l.first) + ")"); l.second(*this, p); } catch (const std::exception& e) { - breep::logger.warning("Exception thrown while calling connection listener " + l.first); - breep::logger.warning(e.what()); + m_log.warning("Exception thrown while calling connection listener " + l.first); + m_log.warning(e.what()); } catch (const std::exception* e) { - breep::logger.warning("Exception thrown while calling connection listener " + l.first); - breep::logger.warning(e->what()); + m_log.warning("Exception thrown while calling connection listener " + l.first); + m_log.warning(e->what()); delete e; } } } else { - breep::logger.info("Peer " + boost::uuids::to_string(p.id()) + ": local connection_predicate rejected the connection"); + m_log.info("Peer " + boost::uuids::to_string(p.id()) + ": local connection_predicate rejected the connection"); m_manager.process_connection_denial(p); } } @@ -319,20 +319,20 @@ inline void breep::basic_peer_manager::peer_connected(peer&& p, unsigned char new_peer.distance(distance); m_manager.process_connected_peer(new_peer); - breep::logger.info("Peer " + boost::uuids::to_string(id) + " connected"); + m_log.info("Peer " + boost::uuids::to_string(id) + " connected"); std::lock_guard lock_guard(m_co_mutex); for (auto& l : m_co_listener) { try { - breep::logger.trace("Calling connection listener (id: " + std::to_string(l.first) + ")"); + m_log.trace("Calling connection listener (id: " + std::to_string(l.first) + ")"); l.second(*this, p); } catch (const std::exception& e) { - breep::logger.warning("Exception thrown while calling connection listener " + l.first); - breep::logger.warning(e.what()); + m_log.warning("Exception thrown while calling connection listener " + l.first); + m_log.warning(e.what()); } catch (const std::exception * e) { - breep::logger.warning("Exception thrown while calling connection listener " + l.first); - breep::logger.warning(e->what()); + m_log.warning("Exception thrown while calling connection listener " + l.first); + m_log.warning(e->what()); delete e; } } @@ -344,20 +344,20 @@ template inline void breep::basic_peer_manager::peer_disconnected(peer& p) { p.distance(std::numeric_limits::max()); - breep::logger.info("Peer " + p.id_as_string() + " disconnected"); + m_log.info("Peer " + p.id_as_string() + " disconnected"); std::lock_guard lock_guard(m_dc_mutex); for(auto& l : m_dc_listener) { try { - breep::logger.trace("Calling disconnection listener (id: " + std::to_string(l.first) + ")"); + m_log.trace("Calling disconnection listener (id: " + std::to_string(l.first) + ")"); l.second(*this, p); } catch (const std::exception& e) { - breep::logger.warning("Exception thrown while calling disconnection listener " + l.first); - breep::logger.warning(e.what()); + m_log.warning("Exception thrown while calling disconnection listener " + l.first); + m_log.warning(e.what()); } catch (const std::exception* e) { - breep::logger.warning("Exception thrown while calling disconnection listener " + l.first); - breep::logger.warning(e->what()); + m_log.warning("Exception thrown while calling disconnection listener " + l.first); + m_log.warning(e->what()); delete e; } } @@ -394,7 +394,7 @@ template inline void breep::basic_peer_manager::forward_if_needed(const peer& source, commands command, const std::vector& data) { const std::vector& peers = m_me.bridging_from_to().at(source.id()); for (const peer* the_peer : peers) { - breep::logger.trace + m_log.trace ("Forwarding " + std::to_string(data.size()) + " octets from " + source.id_as_string() + " to " + the_peer->id_as_string()); m_manager.send(command, data, *the_peer); } @@ -412,7 +412,7 @@ void breep::basic_peer_manager::send_to_handler(const peer& /*source*/, const std::copy(processed_data.data() + 1 + id_size, processed_data.data() + 1 + 2 * id_size, target_id.data); if (!m_peers.count(sender_id)) { - breep::logger.error("Received data from peer " + boost::uuids::to_string(sender_id) + m_log.error("Received data from peer " + boost::uuids::to_string(sender_id) + " which is disconnected."); return; } @@ -420,25 +420,25 @@ void breep::basic_peer_manager::send_to_handler(const peer& /*source*/, const if (m_me.id() == target_id) { const peer& sender(m_peers.at(sender_id)); - breep::logger.debug + m_log.debug ("Received " + std::to_string(data.size() - id_size) + " octets in a private message from " + sender.id_as_string()); std::lock_guard lock_guard(m_data_mutex); for (auto& l : m_data_r_listener) { try { - breep::logger.trace("Calling data listener (id: " + std::to_string(l.first) + ")"); + m_log.trace("Calling data listener (id: " + std::to_string(l.first) + ")"); l.second(*this, sender, processed_data.data() + 1 + 2 * id_size, processed_data.size() - 1 - 2 * id_size, false); } catch (const std::exception& e) { - breep::logger.warning("Exception thrown while calling data listener " + l.first); - breep::logger.warning(e.what()); + m_log.warning("Exception thrown while calling data listener " + l.first); + m_log.warning(e.what()); } catch (const std::exception* e) { - breep::logger.warning("Exception thrown while calling data listener " + l.first); - breep::logger.warning(e->what()); + m_log.warning("Exception thrown while calling data listener " + l.first); + m_log.warning(e->what()); delete e; } } } else { - breep::logger.trace("Forwarding private message to " + boost::uuids::to_string(sender_id)); + m_log.trace("Forwarding private message to " + boost::uuids::to_string(sender_id)); m_manager.send(commands::send_to, data, *m_me.path_to(m_peers.at(sender_id))); } } @@ -451,22 +451,22 @@ void breep::basic_peer_manager::send_to_all_handler(const peer& source, const std::vector processed_data; detail::unmake_little_endian(data, processed_data); - breep::logger.debug + m_log.debug ("Received " + std::to_string(data.size()) + "octets from " + source.id_as_string()); std::lock_guard lock_guard(m_data_mutex); for (auto& l : m_data_r_listener) { try { - breep::logger.trace("Calling data listener (id: " + std::to_string(l.first) + ")"); + m_log.trace("Calling data listener (id: " + std::to_string(l.first) + ")"); l.second(*this, source, processed_data.data(), processed_data.size(), true); } catch (const std::exception& e) { - breep::logger.warning("Exception thrown while calling data listener " + l.first); - breep::logger.warning(e.what()); + m_log.warning("Exception thrown while calling data listener " + l.first); + m_log.warning(e.what()); } catch (const std::exception* e) { - breep::logger.warning("Exception thrown while calling data listener " + l.first); - breep::logger.warning(e->what()); + m_log.warning("Exception thrown while calling data listener " + l.first); + m_log.warning(e->what()); delete e; } } @@ -484,7 +484,7 @@ void breep::basic_peer_manager::forward_to_handler(const peer& source, const m_me.bridging_from_to().at(uuid).push_back(&source); m_me.bridging_from_to().at(source.id()).push_back(&target); - breep::logger.trace("Now forwarding between " + boost::uuids::to_string(uuid) + " and " + source.id_as_string()); + m_log.trace("Now forwarding between " + boost::uuids::to_string(uuid) + " and " + source.id_as_string()); std::vector ldata; unsigned char dist = source.distance(); @@ -509,7 +509,7 @@ void breep::basic_peer_manager::stop_forwarding_handler(const peer& source, c peer& target = m_peers.at(id); - breep::logger.trace("Stopping to forward from " + source.id_as_string() + " to " + target.id_as_string()); + m_log.trace("Stopping to forward from " + source.id_as_string() + " to " + target.id_as_string()); std::vector& v = m_me.bridging_from_to().at(id); auto it = std::find(v.begin(), v.end(), &source); // keeping a vector because this code is unlikely to be called. @@ -579,19 +579,19 @@ void breep::basic_peer_manager::connect_to_handler(const peer& source, const buff2.push_back(ldata[i++]); } - breep::logger.debug("Connecting to " + boost::uuids::to_string(id) + "@" + buff2 + ":" + std::to_string(remote_port)); + m_log.debug("Connecting to " + boost::uuids::to_string(id) + "@" + buff2 + ":" + std::to_string(remote_port)); detail::optional p(m_manager.connect(boost::asio::ip::address::from_string(buff2), remote_port)); ldata.clear(); detail::make_little_endian(buff, ldata); if (p && p->id() == id) { - breep::logger.trace("Connection successful"); + m_log.trace("Connection successful"); m_ignore_predicate = true; - peer_connected(std::move(p.get())); + peer_connected(std::move(*p)); m_ignore_predicate = true; } else { - breep::logger.trace("Connection failed. Requesting a forwarding."); + m_log.trace("Connection failed. Requesting a forwarding."); m_manager.send(commands::forward_to, ldata, source); } } @@ -631,7 +631,7 @@ void breep::basic_peer_manager::update_distance_handler(const peer& source, c try { peer& p = m_peers.at(uuid); if (p.distance() > distance) { - breep::logger.trace("Found a better path for " + p.id_as_string() + " (through " + source.id_as_string() + ")"); + m_log.trace("Found a better path for " + p.id_as_string() + " (through " + source.id_as_string() + ")"); std::vector peer_id; detail::make_little_endian(detail::unowning_linear_container(uuid.data), peer_id); m_manager.send(commands::forward_to, peer_id, source); @@ -654,7 +654,7 @@ void breep::basic_peer_manager::update_distance_handler(const peer& source, c if (p != nullptr) { std::vector peer_id; - breep::logger.trace("Path to " + (*p)->id_as_string() + " found (through " + source.id_as_string() + ")"); + m_log.trace("Path to " + (*p)->id_as_string() + " found (through " + source.id_as_string() + ")"); detail::make_little_endian(detail::unowning_linear_container(uuid.data), peer_id); m_manager.send(commands::forward_to, peer_id, source); std::vector sendable; @@ -678,7 +678,7 @@ void breep::basic_peer_manager::retrieve_distance_handler(const peer& source, unsigned char dist = m_peers.at(uuid).distance(); std::vector ldata; detail::make_little_endian(std::string(&dist, &dist + 1) + std::string(uuid.data, uuid.data + uuid.size()), ldata); - breep::logger.trace("Sending distances to " + source.id_as_string()); + m_log.trace("Sending distances to " + source.id_as_string()); m_manager.send(commands::update_distance, ldata, source); } @@ -707,14 +707,14 @@ void breep::basic_peer_manager::retrieve_peers_handler(const peer& source, co std::vector ldata; detail::make_little_endian(ans, ldata); - breep::logger.trace("Sending peers list to " + source.id_as_string()); + m_log.trace("Sending peers list to " + source.id_as_string()); m_manager.send(commands::peers_list, ldata, source); } template void breep::basic_peer_manager::peers_list_handler(const peer& /*source*/, const std::vector& data) { - breep::logger.trace("Received a list of peers. Scanning through it."); + m_log.trace("Received a list of peers. Scanning through it."); std::vector ldata; detail::unmake_little_endian(data, ldata); @@ -756,7 +756,7 @@ void breep::basic_peer_manager::peers_list_handler(const peer& /*source*/, co if (new_peer->id() != uuid) { m_failed_connections.push_back(std::make_unique(uuid, address, remote_port)); } - peers_list.emplace_back(std::move(new_peer.get())); + peers_list.emplace_back(std::move(*new_peer)); } else { m_failed_connections.push_back(std::make_unique(uuid, address, remote_port)); } diff --git a/include/breep/network/impl/local_peer.tcc b/include/breep/network/impl/local_peer.tcc index 8c5798c..e2d1192 100644 --- a/include/breep/network/impl/local_peer.tcc +++ b/include/breep/network/impl/local_peer.tcc @@ -17,22 +17,12 @@ template inline const breep::basic_peer*& breep::local_peer::path_to(const basic_peer& p) { - try { - return m_path_to_passing_by.at(p.id()); - } catch (const std::out_of_range&) { - breep::logger>.error("Peer " + p.id_as_string() + " disconnected unexpectedly while reading distances"); - throw; - } + return m_path_to_passing_by.at(p.id()); } template inline breep::basic_peer const * const & breep::local_peer::path_to(const basic_peer& p) const { - try { - return m_path_to_passing_by.at(p.id()); - } catch (const std::out_of_range&) { - breep::logger>.error("Peer " + p.id_as_string() + " disconnected unexpectedly while reading distances"); - throw; - } + return m_path_to_passing_by.at(p.id()); } template diff --git a/include/breep/network/local_peer.hpp b/include/breep/network/local_peer.hpp index 41a463f..646f0a3 100644 --- a/include/breep/network/local_peer.hpp +++ b/include/breep/network/local_peer.hpp @@ -3,7 +3,7 @@ /////////////////////////////////////////////////////////////////////////////////////////////////// // // -// Copyright 2017 Lucas Lazare. // +// Copyright 2017-2018 Lucas Lazare. // // This file is part of Breep project which is released under the // // European Union Public License v1.1. If a copy of the EUPL was // // not distributed with this software, you can obtain one at : // @@ -138,6 +138,8 @@ namespace breep { * @since 0.1.0 */ std::unordered_map*, boost::hash> m_path_to_passing_by; + + }; } diff --git a/include/breep/network/tcp/basic_io_manager.hpp b/include/breep/network/tcp/basic_io_manager.hpp index a8f6a30..e44612a 100644 --- a/include/breep/network/tcp/basic_io_manager.hpp +++ b/include/breep/network/tcp/basic_io_manager.hpp @@ -3,7 +3,7 @@ /////////////////////////////////////////////////////////////////////////////////////////////////// // // -// Copyright 2017 Lucas Lazare. // +// Copyright 2017-2018 Lucas Lazare. // // This file is part of Breep project which is released under the // // European Union Public License v1.1. If a copy of the EUPL was // // not distributed with this software, you can obtain one at : // @@ -124,7 +124,7 @@ namespace breep { namespace tcp { void run() final; void set_log_level(log_level ll) const final { - breep::logger.level(ll); + m_log.level(ll); } private: @@ -144,7 +144,7 @@ namespace breep { namespace tcp { } void keep_alive_impl() { - breep::logger.trace("Sending keep_alives"); + m_log.trace("Sending keep_alives"); for (const auto& peers_pair : m_owner->peers()) { send(commands::keep_alive, constant::unused_param, peers_pair.second); } @@ -156,7 +156,7 @@ namespace breep { namespace tcp { std::chrono::milliseconds time_now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()); for (const auto& peers_pair : m_owner->peers()) { if (time_now - peers_pair.second.io_data->timestamp > std::chrono::milliseconds(timeout_millis)) { - breep::logger.trace(peers_pair.second.id_as_string() + " timed out"); + m_log.trace(peers_pair.second.id_as_string() + " timed out"); peers_pair.second.io_data->socket.close(); } } @@ -195,6 +195,8 @@ namespace breep { namespace tcp { boost::asio::deadline_timer m_timeout_dlt; boost::asio::deadline_timer m_keepalive_dlt; + mutable breep::logger m_log{logger::from_class()}; + mutable std::unordered_map>, boost::hash> m_data_queues; }; }} // namespace breep::tcp diff --git a/include/breep/network/tcp/impl/basic_io_manager.tcc b/include/breep/network/tcp/impl/basic_io_manager.tcc index 74d5166..51008ff 100644 --- a/include/breep/network/tcp/impl/basic_io_manager.tcc +++ b/include/breep/network/tcp/impl/basic_io_manager.tcc @@ -1,6 +1,6 @@ /////////////////////////////////////////////////////////////////////////////////////////////////// // // -// Copyright 2017 Lucas Lazare. // +// Copyright 2017-2018 Lucas Lazare. // // This file is part of Breep project which is released under the // // European Union Public License v1.1. If a copy of the EUPL was // // not distributed with this software, you can obtain one at : // @@ -57,7 +57,7 @@ breep::tcp::basic_io_manager.debug("IP dual stack is unsupported on your system. Adding ipv4 listener."); + m_log.debug("IP dual stack is unsupported on your system. Adding ipv4 listener."); } } @@ -140,7 +140,7 @@ void breep::tcp::basic_io_manager::send(commands command, data_iterator write(target); } } catch (const std::out_of_range&) { - breep::logger.warning("Peer " + target.id_as_string() + " disconnected unexpectedly while data was being sent"); + m_log.warning("Peer " + target.id_as_string() + " disconnected unexpectedly while data was being sent"); } } ); @@ -168,15 +168,15 @@ auto breep::tcp::basic_io_manager::connect(const boost::asio::ip::addre boost::system::error_code error; size_t len = socket.read_some(boost::asio::buffer(buffer), error); if (error || len != 8) { - breep::logger.warning("Target peer has not the same protocol ID format than us! (peer at " + m_log.warning("Target peer has not the same protocol ID format than us! (peer at " + address.to_string() + "@" + std::to_string(port) + ")."); return {}; } while (len--) { if (buffer[len] != io_protocol[len]) { - breep::logger.warning("Target peer has not the same io_manager protocol ID than us ([" + m_log.warning("Target peer has not the same io_manager protocol ID than us ([" + address.to_string() + "]:" + std::to_string(port) + ")."); - breep::logger.warning("Our protocol ID: " + std::to_string(IO_PROTOCOL_ID_1) + " " + + m_log.warning("Our protocol ID: " + std::to_string(IO_PROTOCOL_ID_1) + " " + std::to_string(IO_PROTOCOL_ID_2) + ". Their protocol ID: " + std::to_string(detail::read_uint32(buffer)) + " " + std::to_string(detail::read_uint32(buffer, sizeof(uint32_t))) + "."); @@ -205,11 +205,11 @@ auto breep::tcp::basic_io_manager::connect(const boost::asio::ip::addre return detail::optional(); } if (static_cast(command[0]) == commands::connection_refused) { - breep::logger.info("Connection refused ([" + address.to_string() + "]:" + std::to_string(port) + ")"); + m_log.info("Connection refused ([" + address.to_string() + "]:" + std::to_string(port) + ")"); return {}; } if (static_cast(command[0]) != commands::connection_accepted) { - breep::logger.warning("Incompatible protocol, but protocol id match." + m_log.warning("Incompatible protocol, but protocol id match." "(when connecting to [" + address.to_string() + "]:" + std::to_string(port) + ")"); return {}; } @@ -268,9 +268,9 @@ void breep::tcp::basic_io_manager::disconnect(peer& p) { template void breep::tcp::basic_io_manager::run() { m_io_service.reset(); - breep::logger.info("The network is now online."); + m_log.info("The network is now online."); m_io_service.run(); - breep::logger.info("The network is now offline."); + m_log.info("The network is now offline."); } /* PRIVATE */ @@ -433,7 +433,7 @@ void breep::tcp::basic_io_manager::write(const peer& target) const { boost::bind(&io_manager::write_done, this, target) ); } catch (const std::out_of_range&) { - breep::logger.warning("Peer " + target.id_as_string() + " disconnected unexpectedly while data was being sent"); + m_log.warning("Peer " + target.id_as_string() + " disconnected unexpectedly while data was being sent"); } } @@ -446,7 +446,7 @@ void breep::tcp::basic_io_manager::write_done(const peer& target) const write(target); } } catch (const std::out_of_range&) { - breep::logger.warning("Peer " + target.id_as_string() + " disconnected unexpectedly while data was being sent"); + m_log.warning("Peer " + target.id_as_string() + " disconnected unexpectedly while data was being sent"); } } @@ -458,7 +458,7 @@ void breep::tcp::basic_io_manager::accept(boost::system::error_code ec) size_t len = m_socket->read_some(boost::asio::buffer(buffer), ec); if (ec) { - breep::logger.warning("Failed to read data from incomming connection: [" + m_log.warning("Failed to read data from incomming connection: [" + m_socket->remote_endpoint().address().to_string() + "]."); m_socket->close(); } else { @@ -470,7 +470,7 @@ void breep::tcp::basic_io_manager::accept(boost::system::error_code ec) // Reading the protocol ID if (len != 8) { - breep::logger.warning("Incomming connection from [" + m_socket->remote_endpoint().address().to_string() + m_log.warning("Incomming connection from [" + m_socket->remote_endpoint().address().to_string() + "]: they don't have the same protocol ID format than us!"); m_socket = std::make_shared(m_io_service); m_acceptor.async_accept(*m_socket, boost::bind(&io_manager::accept, this, _1)); @@ -478,9 +478,9 @@ void breep::tcp::basic_io_manager::accept(boost::system::error_code ec) } while(len--) { if (buffer[len] != protocol_id[len]) { - breep::logger.warning("Incomming peer has not the same io_manager protocol ID than us ([" + m_log.warning("Incomming peer has not the same io_manager protocol ID than us ([" + m_socket->remote_endpoint().address().to_string() + "])."); - breep::logger.warning("Our protocol ID: " + std::to_string(IO_PROTOCOL_ID_1) + " " + + m_log.warning("Our protocol ID: " + std::to_string(IO_PROTOCOL_ID_1) + " " + std::to_string(IO_PROTOCOL_ID_2) + ". Their protocol ID: " + std::to_string(detail::read_uint32(buffer)) + " " + std::to_string(detail::read_uint32(buffer, sizeof(uint32_t))) + "."); diff --git a/include/breep/util/logger.hpp b/include/breep/util/logger.hpp index 147070a..44ab30c 100644 --- a/include/breep/util/logger.hpp +++ b/include/breep/util/logger.hpp @@ -3,7 +3,7 @@ /////////////////////////////////////////////////////////////////////////////////////////////////// // // -// Copyright 2017 Lucas Lazare. // +// Copyright 2017-2018 Lucas Lazare. // // This file is part of Breep project which is released under the // // European Union Public License v1.1. If a copy of the EUPL was // // not distributed with this software, you can obtain one at : // @@ -20,6 +20,11 @@ #include #include #include +#include + +#if __cplusplus >= 201703L +#include +#endif #include #include @@ -36,162 +41,198 @@ namespace breep { none }; - namespace detail { - namespace logger_cst { - inline const auto start_time = std::chrono::high_resolution_clock::now(); - inline std::mutex logging_lock{}; - inline auto global_maximum_level = log_level::trace; - } - } - - bool operator>=(log_level lhs, log_level rhs); + bool operator>=(log_level lhs, log_level rhs); inline bool operator>=(log_level lhs, log_level rhs) { return static_cast(lhs) >= static_cast(rhs); } namespace detail { - - template - class logger { - public: - - logger() : m_level{log_level::warning} - , tclass{type_traits::universal_name().substr(0, type_traits::universal_name().find('<'))} - , hash{} - {} - - logger& operator()() { - return *this; + namespace loggers_values { +#if __cplusplus >= 201703L + inline const auto start_time = std::chrono::high_resolution_clock::now(); + inline const std::chrono::system_clock::time_point& get_starting_time() { + return start_time; } - /** - * @since 0.1.0 - */ - void trace(const std::string& str) { - if (log_level::trace >= level()) { - log_impl("(trace) ", str); - } + inline auto global_maximum_level = log_level::trace; + inline log_level& get_global_maximum_level() { + return global_maximum_level; } - /** - * @since 0.1.0 - */ - void debug(const std::string& str) { - if (log_level::debug >= level()) { - log_impl("(debug) ", str); - } + inline std::mutex mutex{}; + inline std::mutex& get_mutex() { + return mutex; + } +#else + static const auto start_time = std::chrono::high_resolution_clock::now(); + inline const std::chrono::system_clock::time_point& get_starting_time() { + return start_time; } - /** - * @since 0.1.0 - */ - void info(const std::string& str) { - if (log_level::info >= level()) { - log_impl("(info) ", str); - } + inline log_level& get_global_maximum_level() { + static auto global_maximum_level = log_level::trace; + return global_maximum_level; } - /** - * @since 0.1.0 - */ - void warning(const std::string& str) { - if (log_level::warning >= level()) { - log_impl("(warning)", str); - } + inline std::mutex& get_mutex() { + static std::mutex mutex{}; + return mutex; } +#endif + } + } + + /** + * Basic logger + * + * @since 1.0.0 + */ + class logger { +#if __cplusplus >= 201703L + using string_type = std::string_view; +#else + using string_type = const std::string&; +#endif + public: + + logger(std::string prefix) : m_level{log_level::warning} + , tclass{std::move(prefix)} + , hash{} + {} + + template + static logger from_class() { + return logger(type_traits::universal_name().substr(0, type_traits::universal_name().find('<'))); + } + + /** + * Sets the maximum logging level for all loggers. + * + * @since 1.0.0 + */ + static void set_global_logging_level(log_level ll) { + detail::loggers_values::get_global_maximum_level() = ll; + } - /** - * @since 0.1.0 - */ - void error(const std::string& str) { - if (log_level::error >= level()) { - log_impl("(error) ", str); - } + /** + * @since 1.0.0 + */ + void trace(string_type str) { + if (log_level::trace >= level()) { + log_impl("(trace) ", str); } + } - /** - * @brief calls abort(). - * @since 0.1.0 - */ - void fatal(const std::string& str) { - if (log_level::fatal >= level()) { - log_impl("(fatal) ", str); - } - abort(); + /** + * @since 1.0.0 + */ + void debug(string_type str) { + if (log_level::debug >= level()) { + log_impl("(debug) ", str); } + } - /** - * @brief calls exit(exit_code). - * @since 0.1.0 - */ - void fatal(const std::string& str, int exit_code) { - if (log_level::fatal >= level()) { - log_impl("(fatal) ", str); - } - exit(exit_code); + /** + * @since 1.0.0 + */ + void info(string_type str) { + if (log_level::info >= level()) { + log_impl("(info) ", str); } + } - /** - * sets the logging level - * - * @since 0.1.0 - */ - void level(log_level ll) { - m_level = ll; + /** + * @since 1.0.0 + */ + void warning(string_type str) { + if (log_level::warning >= level()) { + log_impl("(warning)", str); } + } - /** - * gets the logging level - * - * @since 0.1.0 - */ - log_level level() { - return std::max(m_level, logger_cst::global_maximum_level); + /** + * @since 1.0.0 + */ + void error(string_type str) { + if (log_level::error >= level()) { + log_impl("(error) ", str); } + } - private: + /** + * @brief calls std::terminate. + * @since 1.0.0 + */ + void fatal(string_type str) { + if (log_level::fatal >= level()) { + log_impl("(fatal) ", str); + } + std::terminate(); + } - void log_impl(const std::string& level, const std::string& str) { - std::lock_guard lock(detail::logger_cst::logging_lock); - std::clog << str_base(level) << str << std::endl; + /** + * @brief calls exit(exit_code). + * @since 1.0.0 + */ + void fatal(string_type str, int exit_code) { + if (log_level::fatal >= level()) { + log_impl("(fatal) ", str); } + std::exit(exit_code); + } + + /** + * sets the logging level + * + * @since 1.0.0 + */ + void level(log_level ll) { + m_level = ll; + } - std::string str_base(const std::string& str) { - auto count = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - detail::logger_cst::start_time).count(); - auto h = count / 3600; - auto m = (count - h * 3600) / 60; - auto s = count % 60; + /** + * gets the logging level + * + * @since 1.0.0 + */ + log_level level() { + return std::max(m_level, detail::loggers_values::get_global_maximum_level()); + } - std::string h_str = h < 10 ? "0" + std::to_string(h) : std::to_string(h); - std::string m_str = m < 10 ? "0" + std::to_string(m) : std::to_string(m); - std::string s_str = s < 10 ? "0" + std::to_string(s) : std::to_string(s); + private: + void log_impl(string_type level, string_type str) { + std::lock_guard lock(detail::loggers_values::get_mutex()); + std::clog << str_base(level) << str << std::endl; + } - return str + " [" + h_str + ':' + m_str + ':' + s_str + "] " + tclass + "@" - + std::to_string(hash(std::this_thread::get_id())).substr(0, 4) + ": "; + std::string str_base(string_type str) { +#if __cplusplus >= 201703L + return str_base_impl(std::string(str)); +#else + return str_base_impl(str); +#endif + } - } + std::string str_base_impl(const std::string& str) { + auto count = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - detail::loggers_values::get_starting_time()).count(); + auto h = count / 3600; + auto m = (count - h * 3600) / 60; + auto s = count % 60; - log_level m_level; - std::string tclass; - std::hash hash; - }; - } + std::string h_str = h < 10 ? "0" + std::to_string(h) : std::to_string(h); + std::string m_str = m < 10 ? "0" + std::to_string(m) : std::to_string(m); + std::string s_str = s < 10 ? "0" + std::to_string(s) : std::to_string(s); - template - detail::logger logger; - namespace logging { + return str + " [" + h_str + ':' + m_str + ':' + s_str + "] " + tclass + "@" + + std::to_string(hash(std::this_thread::get_id())).substr(0, 4) + ": "; - /** - * Sets the maximum logging level for all loggers. - * - * @since 1.0.0 - */ - void set_max_level(log_level level); - inline void set_max_level(log_level level) { - detail::logger_cst::global_maximum_level = level; } - } + + log_level m_level; + std::string tclass; + std::hash hash; + }; } #endif //BREEP_UTIL_LOGGER_HPP diff --git a/include/breep/util/type_traits.hpp b/include/breep/util/type_traits.hpp index ced06c2..37aa302 100644 --- a/include/breep/util/type_traits.hpp +++ b/include/breep/util/type_traits.hpp @@ -237,19 +237,14 @@ namespace breep { template<> struct identifier_from_tuple> { - static const std::string value; + const std::string value{}; }; - inline const std::string identifier_from_tuple>::value{}; template struct identifier_from_tuple> { - static const std::string value; + const std::string value{"," + networking_traits_impl>::type>().universal_name + + identifier_from_tuple>{}.value}; // if you have an error here, you probably forgot to declare the type T (breep::type_traits>) with BREEP_DECLARE_TEMPLATE(T). }; - template - const std::string identifier_from_tuple>::value = - "," + networking_traits_impl>::type>().universal_name + - identifier_from_tuple>::value; // if you have an error here, you probably forgot to declare the type T (breep::type_traits>) with BREEP_DECLARE_TEMPLATE(T). - // This struct is not technically required, but is // here to help gcc5 to understand what's happening From 9463a60f74b44d3f3251b0f19bb6092199a893e7 Mon Sep 17 00:00:00 2001 From: Lucas Lazare Date: Tue, 20 Nov 2018 19:45:34 -0500 Subject: [PATCH 02/10] Fixing connection issues Before this commit, two peers connected on the same end-point could have issues letting others connecting to both of them, as they'll see the other peer on the same end-point as localhost, thus sending an incorrect ip --- .../breep/network/impl/basic_peer_manager.tcc | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/include/breep/network/impl/basic_peer_manager.tcc b/include/breep/network/impl/basic_peer_manager.tcc index f37338e..e4b6185 100644 --- a/include/breep/network/impl/basic_peer_manager.tcc +++ b/include/breep/network/impl/basic_peer_manager.tcc @@ -712,7 +712,7 @@ void breep::basic_peer_manager::retrieve_peers_handler(const peer& source, co } template -void breep::basic_peer_manager::peers_list_handler(const peer& /*source*/, const std::vector& data) { +void breep::basic_peer_manager::peers_list_handler(const peer& source, const std::vector& data) { m_log.trace("Received a list of peers. Scanning through it."); @@ -742,15 +742,16 @@ void breep::basic_peer_manager::peers_list_handler(const peer& /*source*/, co boost::asio::ip::address address(boost::asio::ip::address::from_string(addr_str)); index += address_size; + if (address.is_loopback()) { + address = source.address(); + } + if (uuid != m_me.id() && m_peers.count(uuid) == 0) { - bool not_found = true; - for (auto it = peers_list.cbegin(), end = peers_list.cend() ; it != end && not_found ; ++it) { - if (it->address() == address && it->connection_port() == remote_port) { - not_found = false; - } - } + auto eq_peer = std::find_if(peers_list.cbegin(), peers_list.cend(), [&address, &remote_port](const peer& p) { + return p.address() == address && p.connection_port() == remote_port; + }); - if (not_found) { + if (eq_peer == peers_list.cend()) { detail::optional new_peer(m_manager.connect(address, remote_port)); if (new_peer) { if (new_peer->id() != uuid) { @@ -761,13 +762,11 @@ void breep::basic_peer_manager::peers_list_handler(const peer& /*source*/, co m_failed_connections.push_back(std::make_unique(uuid, address, remote_port)); } } else { - not_found = true; - for (auto it = peers_list.cbegin(), end = peers_list.cend() ; it != end && not_found ; ++it) { - if (it->id() == uuid) { - not_found = false; - } - } - if (not_found) { + eq_peer == std::find_if(peers_list.cbegin(), peers_list.cend(), [&uuid](const peer& p) { + return p.id() == uuid; + }); + + if (eq_peer == peers_list.cend()) { m_failed_connections.push_back(std::make_unique(uuid, address, remote_port)); } } From f3b2bb250adebf22855ef12684f552840a6c0592 Mon Sep 17 00:00:00 2001 From: Lucas Lazare Date: Sat, 24 Nov 2018 22:09:30 -0500 Subject: [PATCH 03/10] Partial debug of peer bridging --- include/breep/network/basic_peer_manager.hpp | 1 + include/breep/network/detail/commands.hpp | 11 +- .../breep/network/impl/basic_peer_manager.tcc | 202 ++++++++++++------ .../breep/network/tcp/basic_io_manager.hpp | 10 +- .../network/tcp/impl/basic_io_manager.tcc | 13 ++ 5 files changed, 168 insertions(+), 69 deletions(-) diff --git a/include/breep/network/basic_peer_manager.hpp b/include/breep/network/basic_peer_manager.hpp index ad1a29a..f134c03 100644 --- a/include/breep/network/basic_peer_manager.hpp +++ b/include/breep/network/basic_peer_manager.hpp @@ -465,6 +465,7 @@ namespace breep { void send_to_all_handler(const peer& source, const std::vector& data); void forward_to_handler(const peer& source, const std::vector& data); void stop_forwarding_handler(const peer& source, const std::vector& data); + void stopped_forwarding_handler(const peer& source, const std::vector& data); void forwarding_to_handler(const peer& source, const std::vector& data); void connect_to_handler(const peer& source, const std::vector& data); void cant_connect_handler(const peer& source, const std::vector& data); diff --git a/include/breep/network/detail/commands.hpp b/include/breep/network/detail/commands.hpp index 7b1e1ae..6cdf16a 100644 --- a/include/breep/network/detail/commands.hpp +++ b/include/breep/network/detail/commands.hpp @@ -61,17 +61,26 @@ namespace breep { * @details Must be followed by a peer (id) * @sa commands::forward_to * @sa commands::forwarding_to + * @sa commands::stopped_forwarding * * @since 0.1.0 */ stop_forwarding, + /** + * @brief Command to tell a peer you stopped bridging. + * @details Must be followed by a peer (id). This is sent only to the peer that didn't request the bridging halt. + * @sa commands::stop_forwarding + * + * @since 1.0.0 + */ + stopped_forwarding, /** * @brief Command to tell a peer you are bridging for him * @details Must be followed by your own distance to the peer (1 octet) + by a peer (id) * @sa commands::forward_to * @sa commands::stop_forwarding * - * @since 0.1.0 + * @since 0.1.0 */ forwarding_to, /** diff --git a/include/breep/network/impl/basic_peer_manager.tcc b/include/breep/network/impl/basic_peer_manager.tcc index e4b6185..c0a5fd6 100644 --- a/include/breep/network/impl/basic_peer_manager.tcc +++ b/include/breep/network/impl/basic_peer_manager.tcc @@ -53,6 +53,7 @@ breep::basic_peer_manager::basic_peer_manager(T&& manager, unsigned short por m_command_handlers[static_cast(commands::send_to_all)] = &breep::basic_peer_manager::send_to_all_handler; m_command_handlers[static_cast(commands::forward_to)] = &breep::basic_peer_manager::forward_to_handler; m_command_handlers[static_cast(commands::stop_forwarding)] = &breep::basic_peer_manager::stop_forwarding_handler; + m_command_handlers[static_cast(commands::stopped_forwarding)] = &breep::basic_peer_manager::stopped_forwarding_handler; m_command_handlers[static_cast(commands::forwarding_to)] = &breep::basic_peer_manager::forwarding_to_handler; m_command_handlers[static_cast(commands::connect_to)] = &breep::basic_peer_manager::connect_to_handler; m_command_handlers[static_cast(commands::cant_connect)] = &breep::basic_peer_manager::cant_connect_handler; @@ -325,7 +326,7 @@ inline void breep::basic_peer_manager::peer_connected(peer&& p, unsigned char for (auto& l : m_co_listener) { try { m_log.trace("Calling connection listener (id: " + std::to_string(l.first) + ")"); - l.second(*this, p); + l.second(*this, new_peer); } catch (const std::exception& e) { m_log.warning("Exception thrown while calling connection listener " + l.first); @@ -438,8 +439,18 @@ void breep::basic_peer_manager::send_to_handler(const peer& /*source*/, const } } } else { - m_log.trace("Forwarding private message to " + boost::uuids::to_string(sender_id)); - m_manager.send(commands::send_to, data, *m_me.path_to(m_peers.at(sender_id))); + auto& vect = m_me.bridging_from_to().at(source.id()); + if (std::find_if(vect.begin(), vect.end(), [target_id](const peer* p) { return p->id() == target_id; }) != vect.end()) { + try { + m_manager.send(commands::send_to, data, *m_me.path_to(m_peers.at(target_id))); + m_log.trace("Forwarding private message to " + boost::uuids::to_string(target_id)); + } catch (const std::out_of_range&) { + m_log.warning("Received message to forward to " + boost::uuids::to_string(target_id) + " which is unknown"); + } + } else { + m_log.warning("Received private message that local peer was not meant to receive..."); + m_log.warning("(target was " + boost::uuids::to_string(target_id) + ", local peer is " + m_me.id_as_string() + ")."); + } } } @@ -480,23 +491,34 @@ void breep::basic_peer_manager::forward_to_handler(const peer& source, const boost::uuids::uuid uuid; std::copy(id.data(), id.data() + id.size(), uuid.data); - peer& target = m_peers.at(uuid); - m_me.bridging_from_to().at(uuid).push_back(&source); - m_me.bridging_from_to().at(source.id()).push_back(&target); - - m_log.trace("Now forwarding between " + boost::uuids::to_string(uuid) + " and " + source.id_as_string()); - - std::vector ldata; - unsigned char dist = source.distance(); - const boost::uuids::uuid& source_id = source.id(); - detail::make_little_endian(std::string(&dist, &dist + 1) + std::string(source_id.data, source_id.data + source_id.size()), ldata); - m_manager.send(commands::forwarding_to, ldata, target); - - ldata.clear(); - dist = target.distance(); - const boost::uuids::uuid& target_id = target.id(); - detail::make_little_endian(std::string(&dist, &dist + 1) + std::string(target_id.data, target_id.data + target_id.size()), ldata); - m_manager.send(commands::forwarding_to, ldata, source); + try { + peer& target = m_peers.at(uuid); + m_me.bridging_from_to().at(uuid).push_back(&m_peers.at(source.id())); + m_me.bridging_from_to().at(source.id()).push_back(&target); + + m_log.trace("Now bridging from " + source.id_as_string() + " to " + boost::uuids::to_string(uuid)); + + std::vector ldata; + std::uint8_t dist = target.distance(); + const boost::uuids::uuid& target_id = target.id(); + detail::make_little_endian( + std::string(&dist, &dist + 1) + std::string(target_id.begin(), target_id.end()) + , ldata + ); + m_manager.send(commands::forwarding_to, ldata, source); + + ldata.clear(); + dist = source.distance(); + const boost::uuids::uuid& source_id = source.id(); + detail::make_little_endian( + std::string(&dist, &dist + 1) + std::string(source_id.begin(), source_id.end()) + , ldata + ); + m_manager.send(commands::forwarding_to, ldata, target); + + } catch (const std::out_of_range&) { + m_log.warning("Received untreatable forwarding request: from " + source.id_as_string() + " to " + boost::uuids::to_string(uuid)); + } } template @@ -511,19 +533,50 @@ void breep::basic_peer_manager::stop_forwarding_handler(const peer& source, c m_log.trace("Stopping to forward from " + source.id_as_string() + " to " + target.id_as_string()); - std::vector& v = m_me.bridging_from_to().at(id); - auto it = std::find(v.begin(), v.end(), &source); // keeping a vector because this code is unlikely to be called. + std::vector& v = m_me.bridging_from_to().at(target.id()); + auto it = std::find_if(v.begin(), v.end(), [&source](const peer* p) { return p->id() == source.id(); }); if (it != v.end()) { *it = v.back(); v.pop_back(); } std::vector& v2 = m_me.bridging_from_to().at(source.id()); - it = std::find(v2.begin(), v2.end(), &target); // keeping a vector because this code is unlikely to be called. + it = std::find_if(v2.begin(), v2.end(), [&target](const peer* p) { return p->id() == target.id(); }); if (it != v2.end()) { *it = v2.back(); v2.pop_back(); } + + std::vector sendable_id; + detail::make_little_endian(detail::unowning_linear_container(source.id().data), sendable_id); + m_manager.send(commands::stopped_forwarding, sendable_id, target); +} + +template +void breep::basic_peer_manager::stopped_forwarding_handler(const peer& source, const std::vector& data) { + std::string data_str; + detail::unmake_little_endian(data, data_str); + boost::uuids::uuid id; + if (data_str.size() != id.size()) { + m_log.error("Received an id with incorrect size."); + return; + } + std::copy(data_str.begin(), data_str.end(), id.data); + + auto target_it = m_peers.find(id); + if (target_it == m_peers.end()) { + m_log.warning("Ignoring invalid bridge stop acknowledgement from " + source.id_as_string() + " [requested unknown id " + boost::uuids::to_string(id) + "]."); + return; + } + + peer& target = target_it->second; + if (m_me.path_to(target)->id() != source.id()) { + m_log.warning("Received an unused bridge stop acknowledgement from " + source.id_as_string()); + return; + } + + m_log.info(source.id_as_string() + " stopped bridging to " + target.id_as_string()); + peer_disconnected(target); } template @@ -531,27 +584,38 @@ void breep::basic_peer_manager::forwarding_to_handler(const peer& source, con std::string str; detail::unmake_little_endian(data, str); boost::uuids::uuid uuid; - std::copy(str.data() + 1, str.data() + str.size() - 1, uuid.data); + if (str.size() != uuid.size() + 1) { + m_log.error("Received an id with incorrect size."); + return; + } + std::copy(str.begin() + 1, str.end(), uuid.data); unsigned char distance = static_cast(str[0]); - try { - peer& target = m_peers.at(uuid); - m_me.path_to(target) = &source; - m_me.path_to(source) = ⌖ - target.distance(static_cast(distance + 1)); - } catch (std::out_of_range&) { - std::unique_ptr* p = nullptr; - size_t i{m_failed_connections.size()}; - while (p == nullptr && i--) { - if (m_failed_connections[i]->id() == uuid) { - p = &m_failed_connections[i]; - } - } - if (p != nullptr) { + auto target = m_peers.find(uuid); + if (target != m_peers.end()) { + m_me.path_to(target->second) = &source; + target->second.distance(static_cast(distance + 1)); + m_log.trace("Peer " + source.id_as_string() + " is now bridging local peer to " + boost::uuids::to_string(uuid) + + " (distance: " + std::to_string(target->second.distance()) + ")"); + } else { + auto p = std::find_if(m_failed_connections.begin(), m_failed_connections.end(), [&uuid](const std::unique_ptr& p_) { + return p_ && p_->id() == uuid; + }); + + if (p != m_failed_connections.end()) { + m_log.debug("Peer " + boost::uuids::to_string(uuid) + " connected through bridging."); + p->swap(m_failed_connections.back()); peer_connected(std::move(*p->get()), static_cast(distance + 1), m_peers.at(source.id())); m_failed_connections.pop_back(); + } else { + + m_log.warning("Peer " + source.id_as_string() + " attempted to bridge to " + boost::uuids::to_string(uuid) + ", but the latter is not known."); + m_log.warning("Maybe its connection was refused."); + std::vector sendable_id; + detail::make_little_endian(detail::unowning_linear_container(uuid.data), sendable_id); + m_manager.send(commands::stop_forwarding, sendable_id, source); } } } @@ -579,20 +643,30 @@ void breep::basic_peer_manager::connect_to_handler(const peer& source, const buff2.push_back(ldata[i++]); } - m_log.debug("Connecting to " + boost::uuids::to_string(id) + "@" + buff2 + ":" + std::to_string(remote_port)); - detail::optional p(m_manager.connect(boost::asio::ip::address::from_string(buff2), remote_port)); + boost::asio::ip::address addr = boost::asio::ip::address::from_string(buff2); + + peer attempted_peer(id, addr, remote_port); + if (m_predicate(attempted_peer)) { - ldata.clear(); - detail::make_little_endian(buff, ldata); + m_log.debug("Connecting to " + boost::uuids::to_string(id) + "@" + addr.to_string() + ":" + + std::to_string(remote_port)); + detail::optional p(m_manager.connect(addr, remote_port)); - if (p && p->id() == id) { - m_log.trace("Connection successful"); - m_ignore_predicate = true; - peer_connected(std::move(*p)); - m_ignore_predicate = true; + ldata.clear(); + detail::make_little_endian(buff, ldata); + + if (p && p->id() == id) { + m_log.trace("Connection successful"); + m_ignore_predicate = true; + peer_connected(std::move(*p)); + m_ignore_predicate = false; + } else { + m_log.trace("Connection failed. Requesting a forwarding."); + m_failed_connections.push_back(std::make_unique(attempted_peer)); + m_manager.send(commands::forward_to, ldata, source); + } } else { - m_log.trace("Connection failed. Requesting a forwarding."); - m_manager.send(commands::forward_to, ldata, source); + m_log.info("Peer " + attempted_peer.id_as_string() + ": local connection_predicate rejected the outgoing connection"); } } @@ -625,36 +699,34 @@ void breep::basic_peer_manager::update_distance_handler(const peer& source, c std::string ldata; detail::unmake_little_endian(data, ldata); boost::uuids::uuid uuid; - std::copy(ldata.data() + 1, ldata.data() + ldata.size() - 1, uuid.data); - auto distance = static_cast(ldata[0] + 1); - - try { - peer& p = m_peers.at(uuid); + std::copy(++ldata.begin(), ldata.end(), uuid.data); + auto distance = static_cast(ldata[0] + 1); + auto item = m_peers.find(uuid); + if (item != m_peers.end()) { + peer& p = item->second; if (p.distance() > distance) { m_log.trace("Found a better path for " + p.id_as_string() + " (through " + source.id_as_string() + ")"); std::vector peer_id; detail::make_little_endian(detail::unowning_linear_container(uuid.data), peer_id); m_manager.send(commands::forward_to, peer_id, source); + std::vector sendable; - detail::make_little_endian(std::string(&distance, &distance + 1) + std::string(uuid.data, uuid.data + uuid.size()), sendable); + detail::make_little_endian(std::string(&distance, &distance + 1) + std::string(uuid.begin(), uuid.end()), sendable); for (const auto& peer_p : m_peers) { if (peer_p.second.distance() == 0) { m_manager.send(commands::update_distance, sendable, peer_p.second); } } } - } catch (std::out_of_range&) { - std::unique_ptr* p(nullptr); - size_t i{m_failed_connections.size()}; - while (p == nullptr && i--) { - if (m_failed_connections[i]->id() == uuid) { - p = &m_failed_connections[i]; - } - } - if (p != nullptr) { + } else { + auto p = std::find_if(m_failed_connections.begin(), m_failed_connections.end(), [&uuid](const std::unique_ptr& p_) { + return p_ && p_->id() == uuid; + }); + + if (p != m_failed_connections.end()) { std::vector peer_id; - m_log.trace("Path to " + (*p)->id_as_string() + " found (through " + source.id_as_string() + ")"); + m_log.trace("Path to " + (*p)->id_as_string() + " found (through " + source.id_as_string() + "). Requesting bridge"); detail::make_little_endian(detail::unowning_linear_container(uuid.data), peer_id); m_manager.send(commands::forward_to, peer_id, source); std::vector sendable; diff --git a/include/breep/network/tcp/basic_io_manager.hpp b/include/breep/network/tcp/basic_io_manager.hpp index e44612a..2329e7b 100644 --- a/include/breep/network/tcp/basic_io_manager.hpp +++ b/include/breep/network/tcp/basic_io_manager.hpp @@ -94,7 +94,7 @@ namespace breep { namespace tcp { using io_manager = basic_io_manager; using peer = basic_peer; - using data_type = std::shared_ptr>; + using data_type = std::shared_ptr>; // default constructed to 'nullptr' if it's a 'fake' connection (through bridging) explicit basic_io_manager(unsigned short port); @@ -146,7 +146,9 @@ namespace breep { namespace tcp { void keep_alive_impl() { m_log.trace("Sending keep_alives"); for (const auto& peers_pair : m_owner->peers()) { - send(commands::keep_alive, constant::unused_param, peers_pair.second); + if (peers_pair.second.distance() == 0) { + send(commands::keep_alive, constant::unused_param, peers_pair.second); + } } m_keepalive_dlt.expires_from_now(boost::posix_time::millisec(keep_alive_send_millis)); m_keepalive_dlt.async_wait(boost::bind(&io_manager::keep_alive_impl, this)); @@ -155,7 +157,9 @@ namespace breep { namespace tcp { void timeout_impl() { std::chrono::milliseconds time_now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()); for (const auto& peers_pair : m_owner->peers()) { - if (time_now - peers_pair.second.io_data->timestamp > std::chrono::milliseconds(timeout_millis)) { + if (peers_pair.second.distance() == 0 + && time_now - peers_pair.second.io_data->timestamp > std::chrono::milliseconds(timeout_millis)) { + m_log.trace(peers_pair.second.id_as_string() + " timed out"); peers_pair.second.io_data->socket.close(); } diff --git a/include/breep/network/tcp/impl/basic_io_manager.tcc b/include/breep/network/tcp/impl/basic_io_manager.tcc index 51008ff..6ffb3a3 100644 --- a/include/breep/network/tcp/impl/basic_io_manager.tcc +++ b/include/breep/network/tcp/impl/basic_io_manager.tcc @@ -110,6 +110,9 @@ void breep::tcp::basic_io_manager::send(commands command, const data_co template template void breep::tcp::basic_io_manager::send(commands command, data_iterator it, size_type size, const peer& target) const { + if (target.io_data == nullptr) { + m_log.warning("Attempting to direct-send data to a peer with no direct connection."); + } std::vector buff; buff.reserve(2 + size + size / std::numeric_limits::max()); @@ -224,6 +227,12 @@ auto breep::tcp::basic_io_manager::connect(const boost::asio::ip::addre template void breep::tcp::basic_io_manager::process_connected_peer(peer& connected) { + + if (connected.io_data == nullptr) { + // It's a connection through a tunnel, ignored by basic_io_manager. + return; + } + m_data_queues.insert(std::make_pair(connected.id(), std::queue>())); if (connected.io_data->waiting_acceptance_answer) { @@ -258,6 +267,10 @@ void breep::tcp::basic_io_manager::disconnect() { template void breep::tcp::basic_io_manager::disconnect(peer& p) { + if (p.io_data == nullptr) { + return; // bridged peers are ignored. + } + boost::system::error_code error; p.io_data->socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, error); p.io_data->socket.close(error); From 368f683498df503dff86b8de281b418e5b6445c8 Mon Sep 17 00:00:00 2001 From: Lucas Lazare Date: Sat, 24 Nov 2018 22:16:03 -0500 Subject: [PATCH 04/10] Fixing send_to_all with bad source --- include/breep/network/detail/commands.hpp | 6 ++-- .../breep/network/impl/basic_peer_manager.tcc | 33 +++++++++++++++++-- 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/include/breep/network/detail/commands.hpp b/include/breep/network/detail/commands.hpp index 6cdf16a..9d9c86d 100644 --- a/include/breep/network/detail/commands.hpp +++ b/include/breep/network/detail/commands.hpp @@ -42,11 +42,11 @@ namespace breep { send_to, /** * @brief Command for sending data to all peers. - * @details Must be followed by some data + * @details Must be followed by: size of 1 id (in octet, in one octet) + sender id + some data * - * @since 0.1.0 + * @since 1.0.0 */ - send_to_all, + send_to_all, // modified in 1.0.0 /** * @brief Command to indicate a peer he must bridge for you * @details Must be followed by a target peer (id). diff --git a/include/breep/network/impl/basic_peer_manager.tcc b/include/breep/network/impl/basic_peer_manager.tcc index c0a5fd6..1355abc 100644 --- a/include/breep/network/impl/basic_peer_manager.tcc +++ b/include/breep/network/impl/basic_peer_manager.tcc @@ -72,8 +72,14 @@ template template inline void breep::basic_peer_manager::send_to_all(const data_container& data) const { + std::vector transformed_data; + transformed_data.reserve(data.size() + m_me.id().size() + 1); + transformed_data.push_back(m_me.id().size()); + std::copy(m_me.id().begin(), m_me.id().end(), std::back_inserter(transformed_data)); + std::copy(data.begin(), data.end(), std::back_inserter(transformed_data)); + std::vector sendable_data; - detail::make_little_endian(data, sendable_data); + detail::make_little_endian(transformed_data, sendable_data); m_log.debug("Sending " + std::to_string(sendable_data.size()) + " octets"); for (const std::pair& pair : m_peers) { @@ -402,7 +408,7 @@ inline void breep::basic_peer_manager::forward_if_needed(const peer& source, } template -void breep::basic_peer_manager::send_to_handler(const peer& /*source*/, const std::vector& data) { +void breep::basic_peer_manager::send_to_handler(const peer& source, const std::vector& data) { std::vector processed_data; detail::unmake_little_endian(data, processed_data); @@ -465,12 +471,33 @@ void breep::basic_peer_manager::send_to_all_handler(const peer& source, const m_log.debug ("Received " + std::to_string(data.size()) + "octets from " + source.id_as_string()); + uint8_t id_size = processed_data[0]; + boost::uuids::uuid id; + if (id.size() != id_size) { + m_log.warning("Received an id with incorrect size."); + return; + } + std::copy(++processed_data.begin(), processed_data.begin() + id_size + 1, id.begin()); + + const peer* actual_source = &source; + if (id != source.id()) { + m_log.debug("Actual source: " + boost::uuids::to_string(id)); + auto source_it = m_peers.find(id); + if (source_it != m_peers.end()) { + actual_source = &(source_it->second); + } else { + m_log.warning("Received data from unknown peer: " + boost::uuids::to_string(id) + "."); + m_log.warning("Maybe its connection was refused, but someone is bridging"); + return; + } + } + std::lock_guard lock_guard(m_data_mutex); for (auto& l : m_data_r_listener) { try { m_log.trace("Calling data listener (id: " + std::to_string(l.first) + ")"); - l.second(*this, source, processed_data.data(), processed_data.size(), true); + l.second(*this, *actual_source, processed_data.data() + id_size + 1, processed_data.size() - id_size - 1, true); } catch (const std::exception& e) { m_log.warning("Exception thrown while calling data listener " + l.first); From 78c2b51180cae146d78042b34ddfe881cf44f00f Mon Sep 17 00:00:00 2001 From: Lucas Lazare Date: Sat, 24 Nov 2018 22:17:24 -0500 Subject: [PATCH 05/10] Clean up --- include/breep/network/basic_peer.hpp | 5 +- .../breep/network/impl/basic_peer_manager.tcc | 95 ++++++++++++++----- 2 files changed, 75 insertions(+), 25 deletions(-) diff --git a/include/breep/network/basic_peer.hpp b/include/breep/network/basic_peer.hpp index 54f5a50..d87e033 100644 --- a/include/breep/network/basic_peer.hpp +++ b/include/breep/network/basic_peer.hpp @@ -24,6 +24,7 @@ #include #include "breep/network/detail/commands.hpp" +#include "breep/util/type_traits.hpp" namespace breep { @@ -76,12 +77,12 @@ namespace breep { /** * @since 1.0.0 */ - basic_peer& operator=(const basic_peer&) = default; + basic_peer& operator=(const basic_peer&) = delete; /** * @since 1.0.0 */ - basic_peer& operator=(basic_peer&&) = default; + basic_peer& operator=(basic_peer&&) = delete; /** * @return the id of the peer diff --git a/include/breep/network/impl/basic_peer_manager.tcc b/include/breep/network/impl/basic_peer_manager.tcc index 1355abc..8e23065 100644 --- a/include/breep/network/impl/basic_peer_manager.tcc +++ b/include/breep/network/impl/basic_peer_manager.tcc @@ -87,8 +87,7 @@ inline void breep::basic_peer_manager::send_to_all(const data_container& data m_log.trace("Sending to " + pair.second.id_as_string()); m_manager.send(commands::send_to_all, sendable_data, pair.second); } else { - m_log.trace - ("Expecting another peer to forward to " + pair.second.id_as_string() + " (no direct connection)"); + m_log.trace("Expecting another peer to forward to " + pair.second.id_as_string() + " (no direct connection)"); } } } @@ -99,10 +98,11 @@ inline void breep::basic_peer_manager::send_to(const peer& p, const data_cont std::vector processed_data; processed_data.reserve(data.size() + m_me.id().size() * 2 + 1); + processed_data.push_back(static_cast(m_me.id().size())); - std::copy(m_me.id().data, m_me.id().data + m_me.id().size(), std::back_inserter(processed_data)); - std::copy(p.id().data, p.id().data + p.id().size(), std::back_inserter(processed_data)); - std::copy(data.cbegin(), data.cend(), std::back_inserter(processed_data)); + std::copy(m_me.id().begin(), m_me.id().end(), std::back_inserter(processed_data)); + std::copy(p.id().begin(), p.id().end(), std::back_inserter(processed_data)); + std::copy(data.cbegin(), data.cend(), std::back_inserter(processed_data)); std::vector sendable_data; detail::make_little_endian(processed_data, sendable_data); @@ -110,11 +110,12 @@ inline void breep::basic_peer_manager::send_to(const peer& p, const data_cont m_log.debug("Sending private data to " + p.id_as_string()); m_log.debug("(" + std::to_string(data.size()) + " octets)"); + auto path = m_me.path_to(p); if (p.distance() != 0) { - m_log.trace("Passing through " + m_me.path_to(p)->id_as_string() + " (no direct connection)"); + m_log.trace("Passing through " + path->id_as_string() + " (no direct connection)"); } + m_manager.send(commands::send_to, sendable_data, *path); - m_manager.send(commands::send_to, sendable_data, *m_me.path_to(p)); } template @@ -280,9 +281,7 @@ inline void breep::basic_peer_manager::peer_connected(peer&& p) { boost::uuids::uuid id = p.id(); m_peers.emplace(std::make_pair(id, std::move(p))); - std::pair pair_wptr = std::make_pair(id, &(m_peers.at(id))); - m_me.path_to_passing_by().insert(pair_wptr); - + m_me.path_to_passing_by()[id] = &m_peers.at(id); m_me.bridging_from_to().insert(std::make_pair(id, std::vector{})); @@ -318,8 +317,7 @@ inline void breep::basic_peer_manager::peer_connected(peer&& p, unsigned char boost::uuids::uuid id = p.id(); m_peers.emplace(std::make_pair(id, std::move(p))); - std::pair pair_wptr = std::make_pair(id, &bridge); - m_me.path_to_passing_by().insert(pair_wptr); + m_me.path_to_passing_by()[id] = &bridge; m_me.bridging_from_to().insert(std::make_pair(id, std::vector{})); peer& new_peer = m_peers.at(id); @@ -413,10 +411,20 @@ void breep::basic_peer_manager::send_to_handler(const peer& source, const std detail::unmake_little_endian(data, processed_data); size_t id_size = processed_data[0]; + // todo: check if vector is empty before hand boost::uuids::uuid sender_id, target_id; - std::copy(processed_data.data() + 1, processed_data.data() + 1 + id_size, sender_id.data); - std::copy(processed_data.data() + 1 + id_size, processed_data.data() + 1 + 2 * id_size, target_id.data); + if (id_size != sender_id.size()) { + m_log.error("Received an id with incorrect size."); + return; + } + + if (processed_data.size() < 1 + 2 * id_size) { + m_log.error("Unexpectedly small amount of data received."); + return; + } + std::copy(processed_data.begin() + 1, processed_data.begin() + 1 + id_size, sender_id.begin()); + std::copy(processed_data.begin() + 1 + id_size, processed_data.begin() + 1 + 2 * id_size, target_id.begin()); if (!m_peers.count(sender_id)) { m_log.error("Received data from peer " + boost::uuids::to_string(sender_id) @@ -516,7 +524,11 @@ void breep::basic_peer_manager::forward_to_handler(const peer& source, const std::string id; detail::unmake_little_endian(data, id); boost::uuids::uuid uuid; - std::copy(id.data(), id.data() + id.size(), uuid.data); + if (id.size() != uuid.size()) { + m_log.error("Received an id with incorrect size."); + return; + } + std::copy(id.begin(), id.end(), uuid.data); try { peer& target = m_peers.at(uuid); @@ -554,9 +566,22 @@ void breep::basic_peer_manager::stop_forwarding_handler(const peer& source, c std::string data_str; detail::unmake_little_endian(data, data_str); boost::uuids::uuid id; - std::copy(data_str.data(), data_str.data() + data_str.size(), id.data); + if (data_str.size() != id.size()) { + m_log.error("Received an id with incorrect size."); + return; + } + std::copy(data_str.begin(), data_str.end(), id.data); + + + auto target_it = m_peers.find(id); + // TODO: this check every time + // vvvvvvvv + if (target_it == m_peers.end()) { + m_log.info("Ignoring invalid bridge stopping request from " + source.id_as_string() + " [requested unknown id " + boost::uuids::to_string(id) + "]."); + return; + } - peer& target = m_peers.at(id); + peer& target = target_it->second; m_log.trace("Stopping to forward from " + source.id_as_string() + " to " + target.id_as_string()); @@ -660,8 +685,13 @@ void breep::basic_peer_manager::connect_to_handler(const peer& source, const for (; --id_size; ++i) { buff.push_back(ldata[i]); } + boost::uuids::uuid id; - std::copy(buff.data(), buff.data() + buff.size(), id.data); + if (buff.size() != id.size()) { + m_log.error("Received an id with incorrect size."); + return; + } + std::copy(buff.begin(), buff.end(), id.data); id_size = buff.size(); std::string buff2; @@ -703,7 +733,11 @@ void breep::basic_peer_manager::cant_connect_handler(const peer& source, cons detail::unmake_little_endian(data, id_vect); boost::uuids::uuid target_id; - std::copy(id_vect.data(), id_vect.data() + id_vect.size(), target_id.data); + if (id_vect.size() != target_id.size()) { + m_log.error("Received an id with incorrect size."); + return; + } + std::copy(id_vect.begin(), id_vect.end(), target_id.data); std::vector data_to_send; const boost::uuids::uuid& source_id = source.id(); @@ -772,11 +806,15 @@ void breep::basic_peer_manager::retrieve_distance_handler(const peer& source, std::string id; detail::unmake_little_endian(data, id); boost::uuids::uuid uuid; - std::copy(id.data(), id.data() + id.size(), uuid.data); + if (id.size() != uuid.size()) { + m_log.error("Received an id with incorrect size."); + return; + } + std::copy(id.begin(), id.end(), uuid.data); unsigned char dist = m_peers.at(uuid).distance(); std::vector ldata; - detail::make_little_endian(std::string(&dist, &dist + 1) + std::string(uuid.data, uuid.data + uuid.size()), ldata); + detail::make_little_endian(std::string(&dist, &dist + 1) + std::string(uuid.begin(), uuid.end()), ldata); m_log.trace("Sending distances to " + source.id_as_string()); m_manager.send(commands::update_distance, ldata, source); } @@ -831,7 +869,11 @@ void breep::basic_peer_manager::peers_list_handler(const peer& source, const index += 3; std::copy(ldata.cbegin() + index, ldata.cbegin() + index + id_size, std::back_inserter(id)); boost::uuids::uuid uuid; - std::copy(id.data(), id.data() + id.size(), uuid.data); + if (id.size() != uuid.size()) { + m_log.error("Received an id with incorrect size. Skipping."); + continue; + } + std::copy(id.begin(), id.end(), uuid.data); index += id_size; uint8_t address_size = ldata[index++]; @@ -879,6 +921,9 @@ void breep::basic_peer_manager::peers_list_handler(const peer& source, const m_ignore_predicate = false; std::vector sendable_uuid; + if (!m_failed_connections.empty()) { + m_log.debug("There were unsuccessful connections. Asking for distances>bridging."); + } for (std::unique_ptr& peer_ptr : m_failed_connections) { peer_ptr->distance(std::numeric_limits::max()); detail::make_little_endian(detail::unowning_linear_container(peer_ptr->id().data), sendable_uuid); @@ -899,6 +944,10 @@ void breep::basic_peer_manager::peer_disconnection_handler(const peer& source detail::unmake_little_endian(data, local_data); boost::uuids::uuid uuid; - std::copy(local_data.data(), local_data.data() + local_data.size(), uuid.data); + if (local_data.size() != uuid.size()) { + m_log.error("Received an id with incorrect size."); + return; + } + std::copy(local_data.begin(), local_data.end(), uuid.data); peer_disconnected(m_peers.at(uuid)); } From e559e90acffe058c5d67e263f31d4bf96df043be Mon Sep 17 00:00:00 2001 From: Lucas Lazare Date: Tue, 27 Nov 2018 17:59:36 -0500 Subject: [PATCH 06/10] Fixing ipv4 mapped to ipv6 addresses not recognized as loopback --- .../breep/network/impl/basic_peer_manager.tcc | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/include/breep/network/impl/basic_peer_manager.tcc b/include/breep/network/impl/basic_peer_manager.tcc index 8e23065..765f08d 100644 --- a/include/breep/network/impl/basic_peer_manager.tcc +++ b/include/breep/network/impl/basic_peer_manager.tcc @@ -883,7 +883,24 @@ void breep::basic_peer_manager::peers_list_handler(const peer& source, const boost::asio::ip::address address(boost::asio::ip::address::from_string(addr_str)); index += address_size; - if (address.is_loopback()) { + // boost::asio does not consider ipv4-mapped-to-ipv6-loopback-addresses as loopback addresses + // leading to this fix + auto is_loopback = [](const boost::asio::ip::address& addr) { + if (addr.is_v4()) { + return addr.is_loopback(); + } + + boost::asio::ip::address_v6 v6 = addr.to_v6(); + if (!v6.is_v4_mapped()) { + return v6.is_loopback(); + } + + // ipv4 loopback addresses take the whole 127.0.0.0 -> 127.255.255.255 range + // ipv6 mapped to ipv4 store the ipv4 on the last 32bits (this is in network byte order) + return v6.to_bytes()[12] == 127; + }; + + if (is_loopback(address)) { address = source.address(); } From b926a9aaaad750776359c792a46b6f7c40af33c0 Mon Sep 17 00:00:00 2001 From: Lucas Lazare Date: Sun, 2 Dec 2018 00:48:39 -0500 Subject: [PATCH 07/10] Updating bridging --- include/breep/network/impl/basic_peer_manager.tcc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/breep/network/impl/basic_peer_manager.tcc b/include/breep/network/impl/basic_peer_manager.tcc index 765f08d..ca2de75 100644 --- a/include/breep/network/impl/basic_peer_manager.tcc +++ b/include/breep/network/impl/basic_peer_manager.tcc @@ -767,10 +767,17 @@ void breep::basic_peer_manager::update_distance_handler(const peer& source, c peer& p = item->second; if (p.distance() > distance) { m_log.trace("Found a better path for " + p.id_as_string() + " (through " + source.id_as_string() + ")"); + m_log.trace("Assuming immediate briding."); std::vector peer_id; detail::make_little_endian(detail::unowning_linear_container(uuid.data), peer_id); m_manager.send(commands::forward_to, peer_id, source); + const peer*& current_bridger = m_me.path_to(p); + m_manager.send(commands::stop_forwarding, peer_id, *current_bridger); + + current_bridger = &source; + p.distance(static_cast(distance + 1)); + std::vector sendable; detail::make_little_endian(std::string(&distance, &distance + 1) + std::string(uuid.begin(), uuid.end()), sendable); for (const auto& peer_p : m_peers) { From f508ba6dc4b1d69992ac1ea14c074d9a50fc93de Mon Sep 17 00:00:00 2001 From: Lucas Lazare Date: Sun, 2 Dec 2018 00:48:55 -0500 Subject: [PATCH 08/10] Adding commands comments --- include/breep/network/detail/commands.hpp | 25 +++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/include/breep/network/detail/commands.hpp b/include/breep/network/detail/commands.hpp index 9d9c86d..ae72f80 100644 --- a/include/breep/network/detail/commands.hpp +++ b/include/breep/network/detail/commands.hpp @@ -50,6 +50,9 @@ namespace breep { /** * @brief Command to indicate a peer he must bridge for you * @details Must be followed by a target peer (id). + * Caused by: update_distance, [or: upon connection] + * Expected answer: forwarding_to + * * @sa commands::stop_forwarding * @sa commands::forwarding_to * @@ -59,6 +62,8 @@ namespace breep { /** * @brief Command to tell a peer to stop bridging for you. * @details Must be followed by a peer (id) + * Expected answer: none + * * @sa commands::forward_to * @sa commands::forwarding_to * @sa commands::stopped_forwarding @@ -69,6 +74,9 @@ namespace breep { /** * @brief Command to tell a peer you stopped bridging. * @details Must be followed by a peer (id). This is sent only to the peer that didn't request the bridging halt. + * Caused by: stop_forwarding + * Expected answer: none + * * @sa commands::stop_forwarding * * @since 1.0.0 @@ -77,6 +85,9 @@ namespace breep { /** * @brief Command to tell a peer you are bridging for him * @details Must be followed by your own distance to the peer (1 octet) + by a peer (id) + * Caused by: forward_to + * Expected answer: none + * * @sa commands::forward_to * @sa commands::stop_forwarding * @@ -86,6 +97,8 @@ namespace breep { /** * @brief Command to tell a peer to connect to another buddy. * @details Must be followed by a target peer (target port (2 octets) + size of id (in octets, on 1 octet) + id + ip). + * Caused by: cant_connect + * Expected answer: none * * @since 0.1.0 */ @@ -93,6 +106,7 @@ namespace breep { /** * @brief Command to indicate a peer that a connection request failed. * @details Must be followed by a peer (id). + * Expected answer: none * * @since 0.1.0 */ @@ -100,6 +114,8 @@ namespace breep { /** * @brief Command to update its distances (number of links) between a peer. * @details Format : [new distance (on 1 octet)],[peer id] + * Caused by: retrieve_distance + * Expected answer: none * * @since 0.1.0 */ @@ -107,6 +123,8 @@ namespace breep { /** * @brief Command to ask a peer to send its distance from another peer. * @details Must be followed by a peer (id). + * Expected answer: update_distance + * * @sa commands::update_distance * * @since 0.1.0 @@ -114,6 +132,8 @@ namespace breep { retrieve_distance, /** * @brief Command to ask a peer to send the list of peers. + * Expected answer: peers_list + * * @sa commands::update_distance * @sa commands::peers_list * @@ -126,6 +146,8 @@ namespace breep { * Format : [number of peers (2octets)],[peer1],[peer2],...
* with: peerN = [peerN port (2octets)], [peerN id size (in octets, on 1 octet)], [peerN id], * [peerN address size (in octets, on 1 octet)], [peerN address] + * Caused by: retrieve_peers + * Expected answer: none * * @sa commands::retrieve_peers. * @@ -135,6 +157,7 @@ namespace breep { /** * @brief Command to indicate the disconnection of a peer * @details Must be followed by the peer (id). + * Expected answer: none * * @sa commands::peers_list * @@ -143,12 +166,14 @@ namespace breep { peer_disconnection, /** * @brief ignored by basic_peer_manager [only logging it] + * Expected answer: none * * @since 0.1.0 */ keep_alive, /** * @brief Accepting or refusing incomming connection, used by io_managers for process_connected_peer and process_connection_denial. + * Should be ignored at peer_manager level * * @since 1.0.0 */ From 112edb7dca57c8ed9162b1a9082f1f311227eebb Mon Sep 17 00:00:00 2001 From: Lucas Lazare Date: Sun, 2 Dec 2018 00:49:38 -0500 Subject: [PATCH 09/10] Adding missing ctor calls --- .../breep/network/impl/basic_peer_manager.tcc | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/include/breep/network/impl/basic_peer_manager.tcc b/include/breep/network/impl/basic_peer_manager.tcc index ca2de75..47c46fd 100644 --- a/include/breep/network/impl/basic_peer_manager.tcc +++ b/include/breep/network/impl/basic_peer_manager.tcc @@ -413,7 +413,7 @@ void breep::basic_peer_manager::send_to_handler(const peer& source, const std size_t id_size = processed_data[0]; // todo: check if vector is empty before hand - boost::uuids::uuid sender_id, target_id; + boost::uuids::uuid sender_id{}, target_id{}; if (id_size != sender_id.size()) { m_log.error("Received an id with incorrect size."); return; @@ -480,7 +480,7 @@ void breep::basic_peer_manager::send_to_all_handler(const peer& source, const ("Received " + std::to_string(data.size()) + "octets from " + source.id_as_string()); uint8_t id_size = processed_data[0]; - boost::uuids::uuid id; + boost::uuids::uuid id{}; if (id.size() != id_size) { m_log.warning("Received an id with incorrect size."); return; @@ -523,7 +523,7 @@ void breep::basic_peer_manager::forward_to_handler(const peer& source, const std::string id; detail::unmake_little_endian(data, id); - boost::uuids::uuid uuid; + boost::uuids::uuid uuid{}; if (id.size() != uuid.size()) { m_log.error("Received an id with incorrect size."); return; @@ -565,7 +565,7 @@ void breep::basic_peer_manager::stop_forwarding_handler(const peer& source, c std::string data_str; detail::unmake_little_endian(data, data_str); - boost::uuids::uuid id; + boost::uuids::uuid id{}; if (data_str.size() != id.size()) { m_log.error("Received an id with incorrect size."); return; @@ -608,7 +608,7 @@ template void breep::basic_peer_manager::stopped_forwarding_handler(const peer& source, const std::vector& data) { std::string data_str; detail::unmake_little_endian(data, data_str); - boost::uuids::uuid id; + boost::uuids::uuid id{}; if (data_str.size() != id.size()) { m_log.error("Received an id with incorrect size."); return; @@ -635,7 +635,7 @@ template void breep::basic_peer_manager::forwarding_to_handler(const peer& source, const std::vector& data) { std::string str; detail::unmake_little_endian(data, str); - boost::uuids::uuid uuid; + boost::uuids::uuid uuid{}; if (str.size() != uuid.size() + 1) { m_log.error("Received an id with incorrect size."); return; @@ -686,7 +686,7 @@ void breep::basic_peer_manager::connect_to_handler(const peer& source, const buff.push_back(ldata[i]); } - boost::uuids::uuid id; + boost::uuids::uuid id{}; if (buff.size() != id.size()) { m_log.error("Received an id with incorrect size."); return; @@ -732,7 +732,7 @@ void breep::basic_peer_manager::cant_connect_handler(const peer& source, cons std::vector id_vect; detail::unmake_little_endian(data, id_vect); - boost::uuids::uuid target_id; + boost::uuids::uuid target_id{}; if (id_vect.size() != target_id.size()) { m_log.error("Received an id with incorrect size."); return; @@ -759,7 +759,7 @@ template void breep::basic_peer_manager::update_distance_handler(const peer& source, const std::vector& data) { std::string ldata; detail::unmake_little_endian(data, ldata); - boost::uuids::uuid uuid; + boost::uuids::uuid uuid{}; std::copy(++ldata.begin(), ldata.end(), uuid.data); auto distance = static_cast(ldata[0] + 1); auto item = m_peers.find(uuid); @@ -812,7 +812,7 @@ template void breep::basic_peer_manager::retrieve_distance_handler(const peer& source, const std::vector& data) { std::string id; detail::unmake_little_endian(data, id); - boost::uuids::uuid uuid; + boost::uuids::uuid uuid{}; if (id.size() != uuid.size()) { m_log.error("Received an id with incorrect size."); return; @@ -875,7 +875,7 @@ void breep::basic_peer_manager::peers_list_handler(const peer& source, const id.reserve(id_size); index += 3; std::copy(ldata.cbegin() + index, ldata.cbegin() + index + id_size, std::back_inserter(id)); - boost::uuids::uuid uuid; + boost::uuids::uuid uuid{}; if (id.size() != uuid.size()) { m_log.error("Received an id with incorrect size. Skipping."); continue; @@ -967,7 +967,7 @@ void breep::basic_peer_manager::peer_disconnection_handler(const peer& source std::string local_data; detail::unmake_little_endian(data, local_data); - boost::uuids::uuid uuid; + boost::uuids::uuid uuid{}; if (local_data.size() != uuid.size()) { m_log.error("Received an id with incorrect size."); return; From bb59025027c8ee7ea06920279a2752c5b2784e7a Mon Sep 17 00:00:00 2001 From: Lucas Lazare Date: Fri, 7 Dec 2018 16:20:06 -0500 Subject: [PATCH 10/10] Adding custom data type in peer --- include/breep/network/basic_network.hpp | 2 +- include/breep/network/basic_peer.hpp | 19 +++--- include/breep/network/basic_peer_manager.hpp | 8 +-- .../breep/network/detail/object_builder.hpp | 2 +- include/breep/network/impl/basic_peer.tcc | 16 ++--- .../breep/network/impl/basic_peer_manager.tcc | 35 +++++++++- include/breep/network/impl/local_peer.tcc | 12 ++-- include/breep/network/io_manager_base.hpp | 22 +++---- include/breep/network/local_peer.hpp | 22 +++---- include/breep/network/tcp.hpp | 36 ++++++++-- .../breep/network/tcp/basic_io_manager.hpp | 10 +-- .../network/tcp/impl/basic_io_manager.tcc | 66 +++++++++---------- include/breep/util/type_traits.hpp | 28 ++++++++ 13 files changed, 182 insertions(+), 96 deletions(-) diff --git a/include/breep/network/basic_network.hpp b/include/breep/network/basic_network.hpp index 1176963..e8bc2fa 100644 --- a/include/breep/network/basic_network.hpp +++ b/include/breep/network/basic_network.hpp @@ -74,7 +74,7 @@ namespace breep { * @since 0.1.0 */ using inner_io_manager = io_manager; - using peer = basic_peer; + using peer = typename inner_io_manager::peer; using peer_manager = basic_peer_manager; using network = basic_network; diff --git a/include/breep/network/basic_peer.hpp b/include/breep/network/basic_peer.hpp index d87e033..299b045 100644 --- a/include/breep/network/basic_peer.hpp +++ b/include/breep/network/basic_peer.hpp @@ -31,12 +31,15 @@ namespace breep { /** * @class basic_peer basic_peer.hpp * + * @tparam data_structure Data structure that can be used by end user to store any relevant information, accessible through ".data". Must be copyable & default constructible + * * @brief This class represents a network's member * @since 0.1.0 */ - template + template class basic_peer { public: + data_structure data; /** * @since 0.1.0 @@ -67,22 +70,22 @@ namespace breep { /** * @since 0.1.0 */ - basic_peer(const basic_peer& p) = default; + basic_peer(const basic_peer& p) = default; /** * @since 0.1.0 */ - basic_peer(basic_peer&&) = default; + basic_peer(basic_peer&&) = default; /** * @since 1.0.0 */ - basic_peer& operator=(const basic_peer&) = delete; + basic_peer& operator=(const basic_peer&) = delete; /** * @since 1.0.0 */ - basic_peer& operator=(basic_peer&&) = delete; + basic_peer& operator=(basic_peer&&) = delete; /** * @return the id of the peer @@ -96,9 +99,9 @@ namespace breep { */ const boost::asio::ip::address& address() const noexcept; - bool operator==(const basic_peer& lhs) const; + bool operator==(const basic_peer& lhs) const; - bool operator!=(const basic_peer& lhs) const; + bool operator!=(const basic_peer& lhs) const; /** * @return The distance from you to the peer. @@ -164,6 +167,6 @@ namespace breep { #include "impl/basic_peer.tcc" } // namespace breep -BREEP_DECLARE_TEMPLATE(breep::basic_peer) +BREEP_DECLARE_VTEMPLATE(breep::basic_peer) #endif //BREEP_NETWORK_BASIC_PEER_HPP diff --git a/include/breep/network/basic_peer_manager.hpp b/include/breep/network/basic_peer_manager.hpp index f134c03..b7f560a 100644 --- a/include/breep/network/basic_peer_manager.hpp +++ b/include/breep/network/basic_peer_manager.hpp @@ -339,7 +339,7 @@ namespace breep { if (m_port != port) { require_non_running(); m_port = port; - static_cast*>(&m_manager)->port(port); + static_cast*>(&m_manager)->port(port); } } @@ -529,15 +529,15 @@ namespace breep { peer_manager_attorney() = delete; private: - inline static void peer_connected(basic_peer_manager& object, basic_peer&& p) { + inline static void peer_connected(basic_peer_manager& object, typename T::peer&& p) { object.peer_connected(std::move(p)); } - inline static void peer_disconnected(basic_peer_manager& object, basic_peer& p) { + inline static void peer_disconnected(basic_peer_manager& object, typename T::peer& p) { object.peer_disconnected(p); } - inline static void data_received(basic_peer_manager& object, const basic_peer& source, commands command, const std::vector& data) { + inline static void data_received(basic_peer_manager& object, const typename T::peer& source, commands command, const std::vector& data) { object.data_received(source, command, data); } diff --git a/include/breep/network/detail/object_builder.hpp b/include/breep/network/detail/object_builder.hpp index 2833ad6..29aba2e 100644 --- a/include/breep/network/detail/object_builder.hpp +++ b/include/breep/network/detail/object_builder.hpp @@ -178,6 +178,6 @@ namespace breep { namespace detail { }; }} // namespace breep::detail -BREEP_DECLARE_TEMPLATE(breep::detail::object_builder) +BREEP_DECLARE_VTEMPLATE(breep::detail::object_builder) #endif //BREEP_NETWORK_DETAIL_OBJECT_BUILDER_HPP diff --git a/include/breep/network/impl/basic_peer.tcc b/include/breep/network/impl/basic_peer.tcc index ae6950b..8babba3 100644 --- a/include/breep/network/impl/basic_peer.tcc +++ b/include/breep/network/impl/basic_peer.tcc @@ -16,22 +16,22 @@ * @since 0.1.0 */ -template -inline const boost::uuids::uuid& breep::basic_peer::id() const noexcept { +template +inline const boost::uuids::uuid& basic_peer::id() const noexcept { return m_id; } -template -inline const boost::asio::ip::address& breep::basic_peer::address() const noexcept { +template +inline const boost::asio::ip::address& basic_peer::address() const noexcept { return m_address; } -template -inline bool breep::basic_peer::operator==(const basic_peer& lhs) const { +template +inline bool basic_peer::operator==(const basic_peer& lhs) const { return this->m_address == lhs.m_address && this->m_id == lhs.m_id; } -template -inline bool breep::basic_peer::operator!=(const basic_peer& lhs) const { +template +inline bool basic_peer::operator!=(const basic_peer& lhs) const { return this->m_address != lhs.m_address || this->m_id != lhs.m_id; } \ No newline at end of file diff --git a/include/breep/network/impl/basic_peer_manager.tcc b/include/breep/network/impl/basic_peer_manager.tcc index 47c46fd..3163668 100644 --- a/include/breep/network/impl/basic_peer_manager.tcc +++ b/include/breep/network/impl/basic_peer_manager.tcc @@ -44,8 +44,8 @@ breep::basic_peer_manager::basic_peer_manager(T&& manager, unsigned short por , m_thread{nullptr} { - static_assert(std::is_base_of, T>::value, "Specified type not derived from breep::io_manager_base"); - static_cast*>(&m_manager)->owner(this); + static_assert(std::is_base_of, T>::value, "Specified type not derived from breep::io_manager_base"); + static_cast*>(&m_manager)->owner(this); m_waitfor_run.lock(); @@ -757,6 +757,37 @@ void breep::basic_peer_manager::cant_connect_handler(const peer& source, cons template void breep::basic_peer_manager::update_distance_handler(const peer& source, const std::vector& data) { + m_log.trace("Received distance update notification."); + + //TODO: pourquoi donc 1 n'essaye pas de se connected à 3 ?; + //TODO: pourquoi donc 1 n'essaye pas de se connected à 3 ?; + //TODO: pourquoi donc 1 n'essaye pas de se connected à 3 ?; + //TODO: pourquoi donc 1 n'essaye pas de se connected à 3 ?; + //TODO: pourquoi donc 1 n'essaye pas de se connected à 3 ?; + //TODO: pourquoi donc 1 n'essaye pas de se connected à 3 ?; + //TODO: pourquoi donc 1 n'essaye pas de se connected à 3 ?; + //TODO: pourquoi donc 1 n'essaye pas de se connected à 3 ?; + //TODO: pourquoi donc 1 n'essaye pas de se connected à 3 ?; + //TODO: pourquoi donc 1 n'essaye pas de se connected à 3 ?; + //TODO: pourquoi donc 1 n'essaye pas de se connected à 3 ?; + //TODO: pourquoi donc 1 n'essaye pas de se connected à 3 ?; + //TODO: pourquoi donc 1 n'essaye pas de se connected à 3 ?; + //TODO: pourquoi donc 1 n'essaye pas de se connected à 3 ?; + //TODO: pourquoi donc 1 n'essaye pas de se connected à 3 ?; + //TODO: pourquoi donc 1 n'essaye pas de se connected à 3 ?; + //TODO: pourquoi donc 1 n'essaye pas de se connected à 3 ?; + //TODO: pourquoi donc 1 n'essaye pas de se connected à 3 ?; + //TODO: pourquoi donc 1 n'essaye pas de se connected à 3 ?; + //TODO: pourquoi donc 1 n'essaye pas de se connected à 3 ?; + //TODO: pourquoi donc 1 n'essaye pas de se connected à 3 ?; + //TODO: pourquoi donc 1 n'essaye pas de se connected à 3 ?; + //TODO: pourquoi donc 1 n'essaye pas de se connected à 3 ?; + //TODO: pourquoi donc 1 n'essaye pas de se connected à 3 ?; + //TODO: pourquoi donc 1 n'essaye pas de se connected à 3 ?; + //TODO: pourquoi donc 1 n'essaye pas de se connected à 3 ?; + //TODO: pourquoi donc 1 n'essaye pas de se connected à 3 ?; + //TODO: pourquoi donc 1 n'essaye pas de se connected à 3 ?; + std::string ldata; detail::unmake_little_endian(data, ldata); boost::uuids::uuid uuid{}; diff --git a/include/breep/network/impl/local_peer.tcc b/include/breep/network/impl/local_peer.tcc index e2d1192..c399193 100644 --- a/include/breep/network/impl/local_peer.tcc +++ b/include/breep/network/impl/local_peer.tcc @@ -16,31 +16,31 @@ template -inline const breep::basic_peer*& breep::local_peer::path_to(const basic_peer& p) { +inline const typename T::peer*& breep::local_peer::path_to(const typename T::peer& p) { return m_path_to_passing_by.at(p.id()); } template -inline breep::basic_peer const * const & breep::local_peer::path_to(const basic_peer& p) const { +inline typename T::peer const * const & breep::local_peer::path_to(const typename T::peer& p) const { return m_path_to_passing_by.at(p.id()); } template -inline std::unordered_map*, boost::hash>& breep::local_peer::path_to_passing_by() noexcept { +inline std::unordered_map>& breep::local_peer::path_to_passing_by() noexcept { return m_path_to_passing_by; } template -inline const std::unordered_map*, boost::hash>& breep::local_peer::path_to_passing_by() const noexcept { +inline const std::unordered_map>& breep::local_peer::path_to_passing_by() const noexcept { return m_path_to_passing_by; } template -inline std::unordered_map*>, boost::hash>& breep::local_peer::bridging_from_to() noexcept { +inline std::unordered_map, boost::hash>& breep::local_peer::bridging_from_to() noexcept { return m_bridging_from_to; } template -const std::unordered_map*>, boost::hash>& breep::local_peer::bridging_from_to() const noexcept { +const std::unordered_map, boost::hash>& breep::local_peer::bridging_from_to() const noexcept { return m_bridging_from_to; } \ No newline at end of file diff --git a/include/breep/network/io_manager_base.hpp b/include/breep/network/io_manager_base.hpp index daa1290..9b23e88 100644 --- a/include/breep/network/io_manager_base.hpp +++ b/include/breep/network/io_manager_base.hpp @@ -37,7 +37,7 @@ namespace breep { template class basic_peer_manager; - template + template class basic_peer; /** @@ -51,7 +51,7 @@ namespace breep { * * @since 0.1.0 */ - template + template class io_manager_base { public: @@ -71,8 +71,8 @@ namespace breep { * @since 0.1.0 */ template - void send(commands /*command*/, const data_container& /*data*/, const basic_peer& /*peer*/) const { - static_assert(detail::dependent_false, data_container>::value, "Send called without specialisation."); + void send(commands /*command*/, const data_container& /*data*/, const peer& /*peer*/) const { + static_assert(detail::dependent_false::value, "Send called without specialisation."); } /** @@ -91,8 +91,8 @@ namespace breep { * @since 0.1.0 */ template - void send(commands command, data_iterator /*begin*/, size_type /*size*/, const basic_peer& /*peer*/) const { - static_assert(detail::dependent_false, data_iterator>::value, "Send called without specialisation."); + void send(commands command, data_iterator /*begin*/, size_type /*size*/, const peer& /*peer*/) const { + static_assert(detail::dependent_false::value, "Send called without specialisation."); } /** @@ -102,21 +102,21 @@ namespace breep { * * @since 0.1.0 */ - virtual detail::optional> connect(const boost::asio::ip::address&, unsigned short port) = 0; + virtual detail::optional connect(const boost::asio::ip::address&, unsigned short port) = 0; /** * @brief performs any required action after a peer connection. * * @since 0.1.0 */ - virtual void process_connected_peer(basic_peer& peer) = 0; + virtual void process_connected_peer(peer& /*peer*/) = 0; /** * @brief performs any required action when a peer connection was denied. * * @since 1.0.0 */ - virtual void process_connection_denial(basic_peer& peer) = 0; + virtual void process_connection_denial(peer& /*peer*/) = 0; /** * @brief disconnects from the network @@ -128,7 +128,7 @@ namespace breep { /** * @brief disconnects a peer */ - virtual void disconnect(basic_peer& peer) = 0; + virtual void disconnect(peer& /*peer*/) = 0; /** * @brief Network's main thread entry point @@ -166,6 +166,4 @@ namespace breep { }; } // namespace breep -BREEP_DECLARE_TEMPLATE(breep::io_manager_base) - #endif //BREEP_NETWORK_IO_MANAGER_BASE_HPP diff --git a/include/breep/network/local_peer.hpp b/include/breep/network/local_peer.hpp index 646f0a3..c908bdd 100644 --- a/include/breep/network/local_peer.hpp +++ b/include/breep/network/local_peer.hpp @@ -36,12 +36,12 @@ namespace breep { * @since 0.1.0 */ template - class local_peer: public basic_peer { + class local_peer: public io_manager::peer { public: local_peer() - : basic_peer::basic_peer(boost::uuids::random_generator{}(), - boost::asio::ip::address_v4::loopback()) + : io_manager::peer(boost::uuids::random_generator{}(), + boost::asio::ip::address_v4::loopback()) , m_bridging_from_to{} , m_path_to_passing_by{} {} @@ -57,25 +57,25 @@ namespace breep { * * @since 0.1.0 */ - const basic_peer*& path_to(const basic_peer& p); + const typename io_manager::peer*& path_to(const typename io_manager::peer& p); /** * @copydoc local_peer::path_to(const peer&) */ - basic_peer const * const & path_to(const basic_peer& p) const; + typename io_manager::peer const * const & path_to(const typename io_manager::peer& p) const; /** * @return A reference to the private field m_path_to_passing_by * * @since 0.1.0 */ - std::unordered_map*, boost::hash>& + std::unordered_map>& path_to_passing_by() noexcept; /** * @copydoc local_peer::path_to_passing_by() */ - const std::unordered_map*, boost::hash>& + const std::unordered_map>& path_to_passing_by() const noexcept; /** @@ -83,13 +83,13 @@ namespace breep { * * @since 0.1.0 */ - std::unordered_map*>, boost::hash>& + std::unordered_map, boost::hash>& bridging_from_to() noexcept; /** * @copydoc local_peer::bridging_from_to() */ - const std::unordered_map*>, boost::hash>& + const std::unordered_map, boost::hash>& bridging_from_to() const noexcept; private: @@ -117,7 +117,7 @@ namespace breep { * * @since 0.1.0 */ - std::unordered_map*>, boost::hash> m_bridging_from_to; + std::unordered_map, boost::hash> m_bridging_from_to; /** @@ -137,7 +137,7 @@ namespace breep { * * @since 0.1.0 */ - std::unordered_map*, boost::hash> m_path_to_passing_by; + std::unordered_map> m_path_to_passing_by; }; diff --git a/include/breep/network/tcp.hpp b/include/breep/network/tcp.hpp index dff1ec7..9a6bc31 100644 --- a/include/breep/network/tcp.hpp +++ b/include/breep/network/tcp.hpp @@ -26,15 +26,39 @@ #include namespace breep { namespace tcp { - using io_manager = basic_io_manager<1024, 5000, 120000, 54000>; - using peer = basic_peer; - using network = basic_network; - using peer_manager = basic_peer_manager; - template - using netdata_wrapper = basic_netdata_wrapper; + namespace details { + struct empty {}; + } + + template + using io_manager_ds = basic_io_manager; + + template + using peer_ds = basic_peer, data_structure>; + + template + using peer_manager_ds = basic_peer_manager>; + + template + using network_ds = basic_network>; + + template + using netdata_wrapper_ds = basic_netdata_wrapper, T>; + + using io_manager = io_manager_ds; + using peer = peer_ds; + using peer_manager = peer_manager_ds; + using network = network_ds; + template + using netdata_wrapper = netdata_wrapper_ds; }} +BREEP_DECLARE_TEMPLATE(breep::tcp::io_manager_ds) +BREEP_DECLARE_TEMPLATE(breep::tcp::peer_ds) +BREEP_DECLARE_TEMPLATE(breep::tcp::peer_manager_ds) +BREEP_DECLARE_TEMPLATE(breep::tcp::network_ds) + BREEP_DECLARE_TYPE(breep::tcp::io_manager) BREEP_DECLARE_TYPE(breep::tcp::peer) BREEP_DECLARE_TYPE(breep::tcp::peer_manager) diff --git a/include/breep/network/tcp/basic_io_manager.hpp b/include/breep/network/tcp/basic_io_manager.hpp index 2329e7b..fef6651 100644 --- a/include/breep/network/tcp/basic_io_manager.hpp +++ b/include/breep/network/tcp/basic_io_manager.hpp @@ -84,17 +84,19 @@ namespace breep { namespace tcp { * * @since 0.1.0 */ - template - class basic_io_manager final: public io_manager_base> { + template + class basic_io_manager final: public io_manager_base, + basic_peer, data_structure>> { public: // The protocol ID should be changed at each compatibility break. static constexpr uint32_t IO_PROTOCOL_ID_1 = 755960664; // UPDATE THIS TOGETHER WITH THE HASHING FUNCTION +1 [util/type_traits.hpp] static constexpr uint32_t IO_PROTOCOL_ID_2 = 1683390697; // +3 - using io_manager = basic_io_manager; - using peer = basic_peer; + using io_manager = basic_io_manager; + using peer = basic_peer; using data_type = std::shared_ptr>; // default constructed to 'nullptr' if it's a 'fake' connection (through bridging) + using user_data_type = data_structure; explicit basic_io_manager(unsigned short port); diff --git a/include/breep/network/tcp/impl/basic_io_manager.tcc b/include/breep/network/tcp/impl/basic_io_manager.tcc index 6ffb3a3..5485ca9 100644 --- a/include/breep/network/tcp/impl/basic_io_manager.tcc +++ b/include/breep/network/tcp/impl/basic_io_manager.tcc @@ -37,8 +37,8 @@ */ -template -breep::tcp::basic_io_manager::basic_io_manager(unsigned short port) +template +breep::tcp::basic_io_manager::basic_io_manager(unsigned short port) : m_owner(nullptr) , m_io_service{} , m_acceptor(m_io_service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v6(), port)) @@ -63,8 +63,8 @@ breep::tcp::basic_io_manager -breep::tcp::basic_io_manager::basic_io_manager(io_manager&& other) noexcept +template +breep::tcp::basic_io_manager::basic_io_manager(io_manager&& other) noexcept : m_owner(other.m_owner) , m_io_service() , m_acceptor(std::move(other.m_acceptor)) @@ -90,8 +90,8 @@ breep::tcp::basic_io_manager -breep::tcp::basic_io_manager::~basic_io_manager() { +template +breep::tcp::basic_io_manager::~basic_io_manager() { m_acceptor.close(); m_socket->close(); m_io_service.stop(); @@ -101,15 +101,15 @@ breep::tcp::basic_io_manager::~basic_io_manager() { } } -template +template template -void breep::tcp::basic_io_manager::send(commands command, const data_container& data, const peer& target) const { +void breep::tcp::basic_io_manager::send(commands command, const data_container& data, const peer& target) const { send(command, data.cbegin(), data.size(), target); } -template +template template -void breep::tcp::basic_io_manager::send(commands command, data_iterator it, size_type size, const peer& target) const { +void breep::tcp::basic_io_manager::send(commands command, data_iterator it, size_type size, const peer& target) const { if (target.io_data == nullptr) { m_log.warning("Attempting to direct-send data to a peer with no direct connection."); } @@ -149,8 +149,8 @@ void breep::tcp::basic_io_manager::send(commands command, data_iterator ); } -template -auto breep::tcp::basic_io_manager::connect(const boost::asio::ip::address& address, unsigned short port) -> detail::optional { +template +auto breep::tcp::basic_io_manager::connect(const boost::asio::ip::address& address, unsigned short port) -> detail::optional { std::vector io_protocol; io_protocol.reserve(8); detail::insert_uint32(io_protocol, IO_PROTOCOL_ID_1); @@ -225,8 +225,8 @@ auto breep::tcp::basic_io_manager::connect(const boost::asio::ip::addre )); } -template -void breep::tcp::basic_io_manager::process_connected_peer(peer& connected) { +template +void breep::tcp::basic_io_manager::process_connected_peer(peer& connected) { if (connected.io_data == nullptr) { // It's a connection through a tunnel, ignored by basic_io_manager. @@ -248,8 +248,8 @@ void breep::tcp::basic_io_manager::process_connected_peer(peer& connect ); } -template -void breep::tcp::basic_io_manager::process_connection_denial(basic_peer& peer) { +template +void breep::tcp::basic_io_manager::process_connection_denial(peer& peer) { if (peer.io_data->waiting_acceptance_answer) { std::underlying_type_t command[] = { @@ -260,13 +260,13 @@ void breep::tcp::basic_io_manager::process_connection_denial(basic_peer } -template -void breep::tcp::basic_io_manager::disconnect() { +template +void breep::tcp::basic_io_manager::disconnect() { m_io_service.stop(); } -template -void breep::tcp::basic_io_manager::disconnect(peer& p) { +template +void breep::tcp::basic_io_manager::disconnect(peer& p) { if (p.io_data == nullptr) { return; // bridged peers are ignored. } @@ -278,8 +278,8 @@ void breep::tcp::basic_io_manager::disconnect(peer& p) { p.io_data->dynamic_buffer.shrink_to_fit(); } -template -void breep::tcp::basic_io_manager::run() { +template +void breep::tcp::basic_io_manager::run() { m_io_service.reset(); m_log.info("The network is now online."); m_io_service.run(); @@ -288,8 +288,8 @@ void breep::tcp::basic_io_manager::run() { /* PRIVATE */ -template -void breep::tcp::basic_io_manager::owner(basic_peer_manager* owner) { +template +void breep::tcp::basic_io_manager::owner(basic_peer_manager* owner) { if (m_owner == nullptr) { m_owner = owner; @@ -311,8 +311,8 @@ void breep::tcp::basic_io_manager::owner(basic_peer_manager } } -template -void breep::tcp::basic_io_manager::process_read(peer& sender, boost::system::error_code error, std::size_t read) { +template +void breep::tcp::basic_io_manager::process_read(peer& sender, boost::system::error_code error, std::size_t read) { if (!error) { sender.io_data->timestamp = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()); @@ -373,7 +373,7 @@ void breep::tcp::basic_io_manager::process_read(peer& sender, boost::sy // Ends the full packet read process auto packet_processed = [&] { - detail::peer_manager_attorney>::data_received(*m_owner, sender, sender.io_data->last_command, dyn_buff); + detail::peer_manager_attorney>::data_received(*m_owner, sender, sender.io_data->last_command, dyn_buff); dyn_buff.clear(); sender.io_data->last_command = commands::null_command; @@ -435,8 +435,8 @@ void breep::tcp::basic_io_manager::process_read(peer& sender, boost::sy } -template -void breep::tcp::basic_io_manager::write(const peer& target) const { +template +void breep::tcp::basic_io_manager::write(const peer& target) const { try { auto& buffers = m_data_queues.at(target.id()); @@ -450,8 +450,8 @@ void breep::tcp::basic_io_manager::write(const peer& target) const { } } -template -void breep::tcp::basic_io_manager::write_done(const peer& target) const { +template +void breep::tcp::basic_io_manager::write_done(const peer& target) const { try { auto& buffers = m_data_queues.at(target.id()); buffers.pop(); @@ -463,8 +463,8 @@ void breep::tcp::basic_io_manager::write_done(const peer& target) const } } -template -void breep::tcp::basic_io_manager::accept(boost::system::error_code ec) { +template +void breep::tcp::basic_io_manager::accept(boost::system::error_code ec) { if (!ec) { boost::array buffer; diff --git a/include/breep/util/type_traits.hpp b/include/breep/util/type_traits.hpp index 37aa302..b25ab89 100644 --- a/include/breep/util/type_traits.hpp +++ b/include/breep/util/type_traits.hpp @@ -33,6 +33,7 @@ * Please use BREEP_DECLARE_TEMPLATE instead. * * @sa BREEP_DECLARE_TEMPLATE + * @sa BREEP_DECLARE_VTEMPLATE * @sa breep::networking_traits * * @since 0.1.0 @@ -51,11 +52,38 @@ * * @attention When using BREEP_DECLARE_TEMPLATE, no template parameter of the passed class must be a value. * @sa BREEP_DECLARE_TYPE + * @sa BREEP_DECLARE_VTEMPLATE * @sa breep::networking_traits * * @since 0.1.0 */ #define BREEP_DECLARE_TEMPLATE(TType) \ + namespace breep { namespace detail { \ + /* If you have an error here, should probably declare your type with\ + BREEP_DECLARE_TYPE instead of BREEP_DECLARE_TEMPLATE \ + Note that types that have literals as template parameters cannot be declared \ + through this macro; use BREEP_DECLARE_TYPE instead. (ie: BREEP_DECLARE_TYPE(std::array)*/ \ + template \ + struct networking_traits_impl> { \ + networking_traits_impl(); \ + const std::string universal_name = std::string(#TType"<") + networking_traits_impl().universal_name + ">"; \ + }; \ + template /* it's ok if this constructor is not inline */ \ + networking_traits_impl>::networking_traits_impl() = default;\ + }} + +/** + * @brief Used to declare a variadically templatized class, so that it can be sent through the network. Must be called from the global namespace + * @details Specialises networking_traits, giving access to ::universal_name (unmangled) and ::hash_code + * + * @attention When using BREEP_DECLARE_VTEMPLATE, no template parameter of the passed class must be a value. + * @sa BREEP_DECLARE_TYPE + * @sa BREEP_DECLARE_TEMPLATE + * @sa breep::networking_traits + * + * @since 1.0.0 + */ +#define BREEP_DECLARE_VTEMPLATE(TType) \ namespace breep { namespace detail { \ /* If you have an error here, should probably declare your type with\ BREEP_DECLARE_TYPE instead of BREEP_DECLARE_TEMPLATE \