<commit_before>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	cpp-ethereum 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 General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Host.cpp
 * @authors:
 *   <NAME> <<EMAIL>>
 *   <NAME> <<EMAIL>> (Windows version of populateAddresses())
 * @date 2014
 */

#include "Host.h"

#include <sys/types.h>
#ifdef _WIN32
// winsock is already included
// #include <winsock.h>
#else
#include <ifaddrs.h>
#endif

#include <set>
#include <chrono>
#include <thread>
#include <boost/algorithm/string.hpp>
#include <libdevcore/Common.h>
#include <libdevcore/CommonIO.h>
#include <libethcore/Exceptions.h>
#include "Session.h"
#include "Common.h"
#include "Capability.h"
#include "UPnP.h"
using namespace std;
using namespace dev;
using namespace dev::p2p;

// Addresses we will skip during network interface discovery
// Use a vector as the list is small
// Why this and not names?
// Under MacOSX loopback (127.0.0.1) can be named lo0 and br0 are bridges (0.0.0.0)
static const set<bi::address> c_rejectAddresses = {
	{bi::address_v4::from_string("127.0.0.1")},
	{bi::address_v6::from_string("::1")},
	{bi::address_v4::from_string("0.0.0.0")},
	{bi::address_v6::from_string("::")}
};

Host::Host(std::string const& _clientVersion, NetworkPreferences const& _n, bool _start):
	Worker("p2p"),
	m_clientVersion(_clientVersion),
	m_netPrefs(_n),
	m_acceptor(m_ioService),
	m_socket(m_ioService),
	m_key(KeyPair::create())
{
	populateAddresses();
	clog(NetNote) << "Id:" << id().abridged();
	if (_start)
		start();
}

Host::~Host()
{
	stop();
}

void Host::start()
{
	if (isWorking())
		stop();

	for (unsigned i = 0; i < 2; ++i)
	{
		bi::tcp::endpoint endpoint(bi::tcp::v4(), i ? 0 : m_netPrefs.listenPort);
		try
		{
			m_acceptor.open(endpoint.protocol());
			m_acceptor.set_option(ba::socket_base::reuse_address(true));
			m_acceptor.bind(endpoint);
			m_acceptor.listen();
			m_listenPort = i ? m_acceptor.local_endpoint().port() : m_netPrefs.listenPort;
			break;
		}
		catch (...)
		{
			if (i)
			{
				cwarn << "Couldn't start accepting connections on host. Something very wrong with network?\n" << boost::current_exception_diagnostic_information();
				return;
			}
			m_acceptor.close();
			continue;
		}
	}

	determinePublic(m_netPrefs.publicIP, m_netPrefs.upnp);
	ensureAccepting();

	if (!m_public.address().is_unspecified() && (m_nodes.empty() || m_nodes[m_nodesList[0]]->id != id()))
		noteNode(id(), m_public, Origin::Perfect, false);

	clog(NetNote) << "Id:" << id().abridged();

	for (auto const& h: m_capabilities)
		h.second->onStarting();

	startWorking();
}

void Host::stop()
{
	for (auto const& h: m_capabilities)
		h.second->onStopping();

	stopWorking();

	if (m_acceptor.is_open())
	{
		if (m_accepting)
			m_acceptor.cancel();
		m_acceptor.close();
		m_accepting = false;
	}
	if (m_socket.is_open())
		m_socket.close();
	disconnectPeers();

	m_ioService.reset();
}

unsigned Host::protocolVersion() const
{
	return 1;
}

void Host::registerPeer(std::shared_ptr<Session> _s, CapDescs const& _caps)
{
	if (!_s->m_node || !_s->m_node->id)<commit_msg>Bump to P2P protocol version 2.<commit_after>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	cpp-ethereum 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 General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Host.cpp
 * @authors:
 *   <NAME> <<EMAIL>>
 *   <NAME> <<EMAIL>> (Windows version of populateAddresses())
 * @date 2014
 */

#include "Host.h"

#include <sys/types.h>
#ifdef _WIN32
// winsock is already included
// #include <winsock.h>
#else
#include <ifaddrs.h>
#endif

#include <set>
#include <chrono>
#include <thread>
#include <boost/algorithm/string.hpp>
#include <libdevcore/Common.h>
#include <libdevcore/CommonIO.h>
#include <libethcore/Exceptions.h>
#include "Session.h"
#include "Common.h"
#include "Capability.h"
#include "UPnP.h"
using namespace std;
using namespace dev;
using namespace dev::p2p;

// Addresses we will skip during network interface discovery
// Use a vector as the list is small
// Why this and not names?
// Under MacOSX loopback (127.0.0.1) can be named lo0 and br0 are bridges (0.0.0.0)
static const set<bi::address> c_rejectAddresses = {
	{bi::address_v4::from_string("127.0.0.1")},
	{bi::address_v6::from_string("::1")},
	{bi::address_v4::from_string("0.0.0.0")},
	{bi::address_v6::from_string("::")}
};

Host::Host(std::string const& _clientVersion, NetworkPreferences const& _n, bool _start):
	Worker("p2p"),
	m_clientVersion(_clientVersion),
	m_netPrefs(_n),
	m_acceptor(m_ioService),
	m_socket(m_ioService),
	m_key(KeyPair::create())
{
	populateAddresses();
	clog(NetNote) << "Id:" << id().abridged();
	if (_start)
		start();
}

Host::~Host()
{
	stop();
}

void Host::start()
{
	if (isWorking())
		stop();

	for (unsigned i = 0; i < 2; ++i)
	{
		bi::tcp::endpoint endpoint(bi::tcp::v4(), i ? 0 : m_netPrefs.listenPort);
		try
		{
			m_acceptor.open(endpoint.protocol());
			m_acceptor.set_option(ba::socket_base::reuse_address(true));
			m_acceptor.bind(endpoint);
			m_acceptor.listen();
			m_listenPort = i ? m_acceptor.local_endpoint().port() : m_netPrefs.listenPort;
			break;
		}
		catch (...)
		{
			if (i)
			{
				cwarn << "Couldn't start accepting connections on host. Something very wrong with network?\n" << boost::current_exception_diagnostic_information();
				return;
			}
			m_acceptor.close();
			continue;
		}
	}

	determinePublic(m_netPrefs.publicIP, m_netPrefs.upnp);
	ensureAccepting();

	if (!m_public.address().is_unspecified() && (m_nodes.empty() || m_nodes[m_nodesList[0]]->id != id()))
		noteNode(id(), m_public, Origin::Perfect, false);

	clog(NetNote) << "Id:" << id().abridged();

	for (auto const& h: m_capabilities)
		h.second->onStarting();

	startWorking();
}

void Host::stop()
{
	for (auto const& h: m_capabilities)
		h.second->onStopping();

	stopWorking();

	if (m_acceptor.is_open())
	{
		if (m_accepting)
			m_acceptor.cancel();
		m_acceptor.close();
		m_accepting = false;
	}
	if (m_socket.is_open())
		m_socket.close();
	disconnectPeers();

	m_ioService.reset();
}

unsigned Host::protocolVersion() const
{
	return 2;
}

void Host::registerPeer(std::shared_ptr<Session> _s, CapDescs const& _caps)
{
	if (!_s->m_node || !_s->m_node->id)
{'fraction_non_alphanumeric': 0.15430226144511858, 'fraction_numerical': 0.011858797573083288, 'mean_word_length': 4.626842513576416, 'pattern_counts': {'":': 4, '<': 67, '<?xml version=': 0, '>': 53, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 8, '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': '5747606', 'n_tokens_mistral': 2782, 'n_tokens_neox': 2613, 'n_words': 668}