Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue 659 #3

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 23 additions & 2 deletions libraries/app/application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,13 +113,18 @@ namespace detail {
bool _force_validate = false;
application_options _app_options;

///////
// @brief begin making connections to peers
// @param data_dir the directory that contains the configuration information (i.e. data_dir)
//////
void reset_p2p_node(const fc::path& data_dir)
{ try {
_p2p_network = std::make_shared<net::node>("BitShares Reference Implementation");

_p2p_network->load_configuration(data_dir / "p2p");
_p2p_network->set_node_delegate(this);

// The user specified specific seed node(s) that should be connected to
if( _options->count("seed-node") )
{
auto seeds = _options->at("seed-node").as<vector<string>>();
Expand All @@ -140,6 +145,7 @@ namespace detail {
}
}

// The user specified a collection of seed nodes
if( _options->count("seed-nodes") )
{
auto seeds_str = _options->at("seed-nodes").as<string>();
Expand All @@ -161,6 +167,7 @@ namespace detail {
}
else
{
// use the embedded list of seed nodes
// https://bitsharestalk.org/index.php/topic,23715.0.html
vector<string> seeds = {
"104.236.144.84:1777", // puppies (USA)
Expand Down Expand Up @@ -204,12 +211,25 @@ namespace detail {
_p2p_network->listen_to_p2p_network();
ilog("Configured p2p node to listen on ${ip}", ("ip", _p2p_network->get_actual_listening_endpoint()));

if ( _options->count("disable-peer-advertising") && _options->at("dissable_peer_advertising").as<bool>())
_p2p_network->disable_peer_advertising();

if ( _options->count("accept-incoming-connections") )
_p2p_network->accept_incoming_connections( _options->at("accept-incoming-connections").as<bool>());

_p2p_network->connect_to_p2p_network();
// start syncing our chain to what is available on the network
_p2p_network->sync_from(net::item_id(net::core_message_type_enum::block_message_type,
_chain_db->head_block_id()),
std::vector<uint32_t>());
} FC_CAPTURE_AND_RETHROW() }

//////
// @brief for a string, parse into an fc::ip::endpoint
// NOTE: This does a resolve to convert hostnames to IP addresses
// @param endpoint_string the string in the format ip.a.d.dr:port or hostname:port
// @returns a collection of endpoints
//////
std::vector<fc::ip::endpoint> resolve_string_to_ip_endpoints(const std::string& endpoint_string)
{
try
Expand Down Expand Up @@ -968,8 +988,9 @@ void application::set_program_options(boost::program_options::options_descriptio
("replay-blockchain", "Rebuild object graph by replaying all blocks")
("resync-blockchain", "Delete all blocks and re-sync with network from scratch")
("force-validate", "Force validation of all transactions")
("genesis-timestamp", bpo::value<uint32_t>(),
"Replace timestamp from genesis.json with current time plus this many seconds (experts only!)")
("genesis-timestamp", bpo::value<uint32_t>(), "Replace timestamp from genesis.json with current time plus this many seconds (experts only!)")
("disable-peer-advertising", bpo::value<bool>()->implicit_value(false), "Disable peer advertising")
("accept-incoming-connections", bpo::value<bool>()->implicit_value(true), "Accept incoming connections")
;
command_line_options.add(_cli_options);
configuration_file_options.add(_cfg_options);
Expand Down
5 changes: 4 additions & 1 deletion libraries/net/include/graphene/net/node.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@

#include <graphene/chain/protocol/types.hpp>

#include <fc/thread/thread.hpp>

#include <list>

namespace graphene { namespace net {
Expand Down Expand Up @@ -292,7 +294,7 @@ namespace graphene { namespace net {

void disable_peer_advertising();
fc::variant_object get_call_statistics() const;
private:
protected:
std::unique_ptr<detail::node_impl, detail::node_impl_deleter> my;
};

Expand All @@ -312,6 +314,7 @@ namespace graphene { namespace net {
void add_node_delegate(node_delegate* node_delegate_to_add);

virtual uint32_t get_connection_count() const override { return 8; }
std::shared_ptr<fc::thread> get_thread();
private:
struct node_info;
void message_sender(node_info* destination_node);
Expand Down
5 changes: 3 additions & 2 deletions libraries/net/include/graphene/net/peer_connection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -271,8 +271,9 @@ namespace graphene { namespace net
unsigned _send_message_queue_tasks_running; // temporary debugging
#endif
bool _currently_handling_message; // true while we're in the middle of handling a message from the remote system
private:
protected:
peer_connection(peer_connection_delegate* delegate);
private:
void destroy();
public:
static peer_connection_ptr make_shared(peer_connection_delegate* delegate); // use this instead of the constructor
Expand All @@ -286,7 +287,7 @@ namespace graphene { namespace net
void on_connection_closed(message_oriented_connection* originating_connection) override;

void send_queueable_message(std::unique_ptr<queued_message>&& message_to_send);
void send_message(const message& message_to_send, size_t message_send_time_field_offset = (size_t)-1);
virtual void send_message(const message& message_to_send, size_t message_send_time_field_offset = (size_t)-1);
void send_item(const item_id& item_to_send);
void close_connection();
void destroy_connection();
Expand Down
63 changes: 63 additions & 0 deletions libraries/net/node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2157,6 +2157,11 @@ namespace graphene { namespace net { namespace detail {
FC_THROW( "unexpected connection_rejected_message from peer" );
}

//////////////
// @brief a remote peer asks for our list of peers
// @param originating_peer who requested
// @param address_request_message_received the message
//////////////
void node_impl::on_address_request_message(peer_connection* originating_peer, const address_request_message& address_request_message_received)
{
VERIFY_CORRECT_THREAD();
Expand Down Expand Up @@ -2186,6 +2191,11 @@ namespace graphene { namespace net { namespace detail {
originating_peer->send_message(reply);
}

//////////////////
// @brief a remote peer has given us a list of addresses
// @param originating_peer where the message originated
// @param address_message_received the message
//////////////////
void node_impl::on_address_message(peer_connection* originating_peer, const address_message& address_message_received)
{
VERIFY_CORRECT_THREAD();
Expand Down Expand Up @@ -4513,6 +4523,10 @@ namespace graphene { namespace net { namespace detail {
}
}

///////
// @brief listen for incoming p2p connections
// NOTE: can be disabled in configuration
///////
void node_impl::listen_to_p2p_network()
{
VERIFY_CORRECT_THREAD();
Expand Down Expand Up @@ -4608,6 +4622,9 @@ namespace graphene { namespace net { namespace detail {
}
}

/////////
// @brief starts several tasks related to p2p connections and maintenance
/////////
void node_impl::connect_to_p2p_network()
{
VERIFY_CORRECT_THREAD();
Expand Down Expand Up @@ -4670,6 +4687,10 @@ namespace graphene { namespace net { namespace detail {
}, "connect_to_task");
}

/////////
// @brief attempt to connect to a specific endpoint
// @param remote_endpoint the endpoint to connect to
/////////
void node_impl::connect_to_endpoint(const fc::ip::endpoint& remote_endpoint)
{
VERIFY_CORRECT_THREAD();
Expand Down Expand Up @@ -4830,6 +4851,11 @@ namespace graphene { namespace net { namespace detail {
// peer_to_disconnect->close_connection();
}

////////////
// @brief listen on a particular endpoint
// @param ep the endpoint
// @param wait_if_not_available wait if the endpoint is busy
////////////
void node_impl::listen_on_endpoint( const fc::ip::endpoint& ep, bool wait_if_not_available )
{
VERIFY_CORRECT_THREAD();
Expand All @@ -4838,13 +4864,22 @@ namespace graphene { namespace net { namespace detail {
save_node_configuration();
}

///////////////
// @brief configure the node to accept incoming connections
// @param accept true to accept, false to ignore
///////////////
void node_impl::accept_incoming_connections(bool accept)
{
VERIFY_CORRECT_THREAD();
_node_configuration.accept_incoming_connections = accept;
save_node_configuration();
}

///////////
// @brief listens on all interfaces
// @param port the port to listen on (0 allows system to select unused port)
// @param wait_if_not_available wait if endpoint is busy
///////////
void node_impl::listen_on_port( uint16_t port, bool wait_if_not_available )
{
VERIFY_CORRECT_THREAD();
Expand Down Expand Up @@ -5173,11 +5208,18 @@ namespace graphene { namespace net { namespace detail {
INVOKE_IN_IMPL(load_configuration, configuration_directory);
}

///////
// @brief listen for incoming p2p connections
// NOTE: can be disabled in configuration
///////
void node::listen_to_p2p_network()
{
INVOKE_IN_IMPL(listen_to_p2p_network);
}

/////////
// @brief starts several tasks related to p2p connections and maintenance
/////////
void node::connect_to_p2p_network()
{
INVOKE_IN_IMPL(connect_to_p2p_network);
Expand All @@ -5188,21 +5230,39 @@ namespace graphene { namespace net { namespace detail {
INVOKE_IN_IMPL(add_node, ep);
}

/////////
// @brief attempt to connect to a specific endpoint
// @param remote_endpoint the endpoint to connect to
/////////
void node::connect_to_endpoint( const fc::ip::endpoint& remote_endpoint )
{
INVOKE_IN_IMPL(connect_to_endpoint, remote_endpoint);
}

////////////
// @brief listen on a particular endpoint
// @param ep the endpoint
// @param wait_if_not_available wait if the endpoint is busy
////////////
void node::listen_on_endpoint(const fc::ip::endpoint& ep , bool wait_if_not_available)
{
INVOKE_IN_IMPL(listen_on_endpoint, ep, wait_if_not_available);
}

///////////////
// @brief configure the node to accept incoming connections
// @param accept true to accept, false to ignore
///////////////
void node::accept_incoming_connections(bool accept)
{
INVOKE_IN_IMPL(accept_incoming_connections, accept);
}

///////////
// @brief listens on all interfaces
// @param port the port to listen on (0 allows system to select unused port)
// @param wait_if_not_available wait if endpoint is busy
///////////
void node::listen_on_port( uint16_t port, bool wait_if_not_available )
{
INVOKE_IN_IMPL(listen_on_port, port, wait_if_not_available);
Expand Down Expand Up @@ -5366,6 +5426,9 @@ namespace graphene { namespace net { namespace detail {
network_nodes.push_back(new node_info(node_delegate_to_add));
}

std::shared_ptr<fc::thread> simulated_network::get_thread() { return my->_thread; }


namespace detail
{
#define ROLLING_WINDOW_SIZE 1000
Expand Down
9 changes: 8 additions & 1 deletion programs/witness_node/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,18 @@ class deduplicator
const boost::shared_ptr<bpo::option_description> (*modifier)(const boost::shared_ptr<bpo::option_description>&);
};

//////////////////
// @brief load the configuration file
// @param config_ini_path the full path to the config.ini file
// @param cfg_options the known configuration options with a default value
// @param options the options passed on the command line
//////////////////
static void load_config_file( const fc::path& config_ini_path, const bpo::options_description& cfg_options,
bpo::variables_map& options )
{
deduplicator dedup;
bpo::options_description unique_options("Graphene Witness Node");
// loop through known configuration options, making sure they are unique
for( const boost::shared_ptr<bpo::option_description> opt : cfg_options.options() )
{
const boost::shared_ptr<bpo::option_description> od = dedup.next(opt);
Expand All @@ -105,7 +112,7 @@ static void load_config_file( const fc::path& config_ini_path, const bpo::option

// get the basic options
bpo::store(bpo::parse_config_file<char>(config_ini_path.preferred_string().c_str(),
unique_options, true), options);
unique_options, true), options);

// try to get logging options from the config file.
try
Expand Down
90 changes: 90 additions & 0 deletions tests/tests/p2p_node_tests.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* Copyright (c) 2015 Cryptonomex, Inc., and contributors.
*
* The MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <memory>
#include <boost/test/unit_test.hpp>
#include <boost/assign/list_of.hpp>

#include <fc/thread/thread.hpp>

#include <graphene/net/node.hpp>
#include <graphene/chain/protocol/fee_schedule.hpp>

#include <graphene/net/peer_connection.hpp>

namespace graphene
{
namespace net
{
namespace detail
{
class node_impl : public graphene::net::peer_connection_delegate
{
public:
void on_message( peer_connection* originating_peer,
const message& received_message );
void on_connection_closed(peer_connection* originating_peer);
message get_message_for_item(const item_id& item);
};
}
}
}

class test_node : public graphene::net::simulated_network {
public:
test_node(const std::string& name) : simulated_network(name) {}
void on_message(graphene::net::peer_connection_ptr originating_peer, const graphene::net::message& received_message)
{
get_thread()->async([&](){ return my->on_message(originating_peer.get(), received_message); }, "thread invoke for method on_message").wait();
}
};

class test_peer : public graphene::net::peer_connection
{
public:
std::shared_ptr<graphene::net::message> message_received;
void send_message(const graphene::net::message& message_to_send, size_t message_send_time_field_offset = (size_t)-1) override
{
message_received = std::shared_ptr<graphene::net::message>(new graphene::net::message(message_to_send));
}
public:
test_peer(graphene::net::peer_connection_delegate* del) : graphene::net::peer_connection(del) {
message_received = nullptr;
}

};

BOOST_AUTO_TEST_CASE( p2p_disable_peer_advertising )
{
// first try without the disable-peer-advertising parameter
test_node my_node("Hello");
graphene::net::detail::node_impl del;
std::shared_ptr<test_peer> my_peer(new test_peer{&del});
// add a node so it can be returned by the request
// make the request for peers
graphene::net::address_request_message address_request_message_received;
my_node.on_message(my_peer, address_request_message_received);
BOOST_CHECK(my_peer->message_received != nullptr);
// now try with "disable_peer_advertising" set
my_node.disable_peer_advertising();
}