<commit_before>/**
 * Copyright (c) 2011-2018 libbitcoin developers (see AUTHORS)
 *
 * This file is part of libbitcoin.
 *
 * libbitcoin is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version. For more information see LICENSE.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#include <bitcoin/bitcoin/network/protocol.hpp>

#include <cstddef>
#include <cstdint>
#include <functional>
#include <memory>
#include <system_error>
#include <thread>
#include <vector>
#include <boost/date_time.hpp>
#include <boost/filesystem.hpp>
#include <boost/format.hpp>
#include <bitcoin/bitcoin/config/authority.hpp>
#include <bitcoin/bitcoin/config/endpoint.hpp>
#include <bitcoin/bitcoin/error.hpp>
#include <bitcoin/bitcoin/network/hosts.hpp>
#include <bitcoin/bitcoin/network/handshake.hpp>
#include <bitcoin/bitcoin/network/seeder.hpp>
#include <bitcoin/bitcoin/utility/logger.hpp>
#include <bitcoin/bitcoin/utility/threadpool.hpp>

namespace libbitcoin {
namespace network {

using std::placeholders::_1;
using std::placeholders::_2;
using boost::filesystem::path;
using boost::format;
using boost::posix_time::time_duration;
using boost::posix_time::seconds;

protocol::protocol(threadpool& pool, hosts& hosts, handshake& shake,
    network& net, uint16_t port, bool relay, size_t max_outbound,
    size_t max_inbound, const config::endpoint::list& seeds)
  : strand_(pool),
    host_pool_(hosts),
    handshake_(shake),
    network_(net),
    seeder_(pool, hosts, shake, net, seeds),
    channel_subscriber_(std::make_shared<channel_subscriber>(pool)),
    inbound_port_(port),
    max_inbound_(max_inbound),
    max_outbound_(max_outbound),
    relay_inbound_and_outbound_(relay)
{
}

void protocol::stop(completion_handler handle_complete)
{
    host_pool_.save(
        strand_.wrap(&protocol::handle_hosts_save,
            this, _1, handle_complete));
}

void protocol::handle_hosts_save(const std::error_code& ec,
    completion_handler handle_complete)
{
    if (ec)
    {
        log_error(LOG_PROTOCOL)
            << "Failure saving hosts file: " << ec.message();
    }

    // Stop all established channels.
    notify_stop();

    // Return is asynchronous, threads may still be stopping.
    handle_complete(ec);
}

void protocol::notify_stop()
{
    // Stop protocol subscribers.
    channel_subscriber_->relay(error::service_stopped, nullptr);

    // Notify all channels to stop.
    for (const auto node: outbound_connections_)
        node->stop(error::channel_stopped);

    for (const auto node: manual_connections_)
        node->stop(error::channel_stopped);

    for (const auto node: inbound_connections_)
        node->stop(error::channel_stopped);
}

void protocol::start(completion_handler handle_complete)
{
    if (max_outbound_ == 0)
    {
        // Skip load/seed hosts if we aren't connecting outbound.
        start_connecting(handle_complete, relay_inbound_and_outbound_);
        return;
    }<commit_msg>User error::service_stopping for protocol shutdown.<commit_after>/**
 * Copyright (c) 2011-2018 libbitcoin developers (see AUTHORS)
 *
 * This file is part of libbitcoin.
 *
 * libbitcoin is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version. For more information see LICENSE.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#include <bitcoin/bitcoin/network/protocol.hpp>

#include <cstddef>
#include <cstdint>
#include <functional>
#include <memory>
#include <system_error>
#include <thread>
#include <vector>
#include <boost/date_time.hpp>
#include <boost/filesystem.hpp>
#include <boost/format.hpp>
#include <bitcoin/bitcoin/config/authority.hpp>
#include <bitcoin/bitcoin/config/endpoint.hpp>
#include <bitcoin/bitcoin/error.hpp>
#include <bitcoin/bitcoin/network/hosts.hpp>
#include <bitcoin/bitcoin/network/handshake.hpp>
#include <bitcoin/bitcoin/network/seeder.hpp>
#include <bitcoin/bitcoin/utility/logger.hpp>
#include <bitcoin/bitcoin/utility/threadpool.hpp>

namespace libbitcoin {
namespace network {

using std::placeholders::_1;
using std::placeholders::_2;
using boost::filesystem::path;
using boost::format;
using boost::posix_time::time_duration;
using boost::posix_time::seconds;

protocol::protocol(threadpool& pool, hosts& hosts, handshake& shake,
    network& net, uint16_t port, bool relay, size_t max_outbound,
    size_t max_inbound, const config::endpoint::list& seeds)
  : strand_(pool),
    host_pool_(hosts),
    handshake_(shake),
    network_(net),
    seeder_(pool, hosts, shake, net, seeds),
    channel_subscriber_(std::make_shared<channel_subscriber>(pool)),
    inbound_port_(port),
    max_inbound_(max_inbound),
    max_outbound_(max_outbound),
    relay_inbound_and_outbound_(relay)
{
}

void protocol::stop(completion_handler handle_complete)
{
    host_pool_.save(
        strand_.wrap(&protocol::handle_hosts_save,
            this, _1, handle_complete));
}

void protocol::handle_hosts_save(const std::error_code& ec,
    completion_handler handle_complete)
{
    if (ec)
    {
        log_error(LOG_PROTOCOL)
            << "Failure saving hosts file: " << ec.message();
    }

    // Stop all established channels.
    notify_stop();

    // Return is asynchronous, threads may still be stopping.
    handle_complete(ec);
}

void protocol::notify_stop()
{
    // Stop protocol subscribers.
    channel_subscriber_->relay(error::service_stopped, nullptr);

    // Notify all channels to stop.
    for (const auto node: outbound_connections_)
        node->stop(error::service_stopped);

    for (const auto node: manual_connections_)
        node->stop(error::service_stopped);

    for (const auto node: inbound_connections_)
        node->stop(error::service_stopped);
}

void protocol::start(completion_handler handle_complete)
{
    if (max_outbound_ == 0)
    {
        // Skip load/seed hosts if we aren't connecting outbound.
        start_connecting(handle_complete, relay_inbound_and_outbound_);
        return;
    }
{'fraction_non_alphanumeric': 0.10657820440429136, 'fraction_numerical': 0.004234895539243365, 'mean_word_length': 4.3755690440060695, 'pattern_counts': {'":': 0, '<': 53, '<?xml version=': 0, '>': 53, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1275035', 'n_tokens_mistral': 2169, 'n_tokens_neox': 2108, 'n_words': 594}