/usr/include/bitcoin/network/protocol.hpp is in libbitcoin-dev 2.0-2.2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 | /*
* Copyright (c) 2011-2013 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/>.
*/
#ifndef LIBBITCOIN_PROTOCOL_HPP
#define LIBBITCOIN_PROTOCOL_HPP
#include <memory>
#include <system_error>
#include <bitcoin/types.hpp>
#include <bitcoin/primitives.hpp>
#include <bitcoin/network/channel.hpp>
#include <bitcoin/threadpool.hpp>
#include <bitcoin/utility/subscriber.hpp>
#include <bitcoin/utility/async_parallel.hpp>
namespace libbitcoin {
class hosts;
class handshake;
class protocol
{
public:
typedef std::function<void (const std::error_code&)> completion_handler;
typedef std::function<void (const std::error_code&, size_t)>
fetch_connection_count_handler;
typedef std::function<void (const std::error_code&,
channel_ptr)> channel_handler;
typedef std::function<void (const std::error_code&, size_t)>
broadcast_handler;
protocol(threadpool& pool, hosts& hsts,
handshake& shake, network& net);
protocol(const protocol&) = delete;
void operator=(const protocol&) = delete;
/**
* Set max_outbound connections soft limit.
*/
void set_max_outbound(size_t max_outbound);
/**
* Set the filename to load the hosts file from.
*/
void set_hosts_filename(const std::string& hosts_filename);
/**
* If called, then this service will not listen for incoming
* connections. Must be called before start().
*/
void disable_listener();
/**
* Perform full initialization sequence.
* Internally calls bootstrap() and then run().
*
* @param[in] handle_complete Completion handler for start operation.
* @code
* void handle_complete(
* const std::error_code& ec // Status of operation
* );
* @endcode
*/
void start(completion_handler handle_complete);
/**
* Gracefully close down.
*
* @param[in] handle_complete Completion handler for start operation.
* @code
* void handle_complete(
* const std::error_code& ec // Status of operation
* );
* @endcode
*/
void stop(completion_handler handle_complete);
/**
* Begin initialization sequence of performing node discovery and
* starting other network services.
*
* @param[in] handle_complete Completion handler for start operation.
* @code
* void handle_complete(
* const std::error_code& ec // Status of operation
* );
* @endcode
*/
void bootstrap(completion_handler handle_complete);
/**
* Starts the internal run loop for this service.
*/
void run();
/**
* Fetch number of connections maintained by this service.
*
* @param[in] handle_fetch Completion handler for fetch operation.
* @code
* void handle_fetch(
* const std::error_code& ec, // Status of operation
* size_t connection_count // Number of connections
* );
* @endcode
*/
void fetch_connection_count(
fetch_connection_count_handler handle_fetch);
/**
* Create a manual connection to a specific node. If disconnected
* this service will keep attempting to reconnect until successful.
*
* @param[in] hostname // Hostname
* @param[in] port // Port
*/
void maintain_connection(const std::string& hostname, uint16_t port);
/**
* Subscribe to new connections established to other nodes.
* This method must be called again to stay subscribed as
* handlers are deregistered after being called.
*
* When this protocol service is stopped, any subscribed handlers
* will be called with the error_code set to error::service_stopped.
*
* @param[in] handle_channel Handler for new connection.
* @code
* void handle_channel(
* const std::error_code& ec, // Status of operation
* channel_ptr node // Communication channel to new node
* );
* @endcode
*/
void subscribe_channel(channel_handler handle_channel);
/**
* Broadcast a message to all nodes in our connection list.
*
* @param[in] packet Message packet to broadcast
* @param[in] handle_send Called after every send operation.
* @code
* void handle_send(
* const std::error_code& ec, // Status of operation
* size_t total_nodes // Total number of connected nodes
* // when the operation began.
* );
* @endcode
*/
template <typename Message>
void broadcast(const Message& packet, broadcast_handler handle_send)
{
strand_.post(
std::bind(&protocol::do_broadcast<Message>,
this, packet, handle_send));
}
private:
struct connection_info
{
network_address_type address;
channel_ptr node;
};
typedef std::vector<connection_info> connection_list;
enum class connect_state
{
none,
finding_peer,
connecting,
established,
stopped
};
typedef std::vector<connect_state> connect_state_list;
typedef size_t slot_index;
// Accepted connections
typedef std::vector<channel_ptr> channel_ptr_list;
typedef subscriber<const std::error_code&, channel_ptr>
channel_subscriber_type;
// start sequence
void handle_bootstrap(const std::error_code& ec,
atomic_counter_ptr count_paths, completion_handler handle_complete);
void handle_start_handshake_service(const std::error_code& ec,
atomic_counter_ptr count_paths, completion_handler handle_complete);
// stop sequence
void handle_save(const std::error_code& ec,
completion_handler handle_complete);
// bootstrap sequence
void load_hosts(const std::error_code& ec,
completion_handler handle_complete);
void if_0_seed(const std::error_code& ec, size_t hosts_count,
completion_handler handle_complete);
// seed addresses from dns seeds
class seeds
: public std::enable_shared_from_this<seeds>
{
public:
seeds(protocol* parent);
void start(completion_handler handle_complete);
private:
void error_case(const std::error_code& ec);
void connect_dns_seed(const std::string& hostname);
void request_addresses(const std::error_code& ec,
channel_ptr dns_seed_node);
void handle_send_get_address(const std::error_code& ec);
void save_addresses(const std::error_code& ec,
const address_type& packet, channel_ptr);
void handle_store(const std::error_code& ec);
completion_handler handle_complete_;
size_t ended_paths_;
bool finished_;
// From parent
io_service::strand& strand_;
hosts& hosts_;
handshake& handshake_;
network& network_;
};
std::shared_ptr<seeds> load_seeds_;
friend class seeds;
// run loop
// Connect outwards
void try_outbound_connects();
// This function is called in these places:
//
// 1. try_outbound_connects() calls it n times.
// Called by run() at the start.
// 2. If we fetch a random node address that we are already
// connected to in attempt_connect().
// 3. If we fail to connect to said address in handle_connect().
// 4. If the channel is stopped manually or there is an error
// (such as a disconnect). See setup_new_channel() for the
// subscribe call.
void try_connect_once(slot_index slot);
void attempt_connect(const std::error_code& ec,
const network_address_type& packet, slot_index slot);
void handle_connect(const std::error_code& ec, channel_ptr node,
const network_address_type& address, slot_index slot);
// Manual connections
void handle_manual_connect(const std::error_code& ec, channel_ptr node,
const std::string& hostname, uint16_t port);
// Accept inwards connections
void handle_listen(const std::error_code& ec, acceptor_ptr accept);
void handle_accept(const std::error_code& ec, channel_ptr node,
acceptor_ptr accept);
// Channel setup
void setup_new_channel(channel_ptr node);
// Remove channels from lists when disconnected.
void outbound_channel_stopped(
const std::error_code& ec, channel_ptr which_node, slot_index slot);
void manual_channel_stopped(
const std::error_code& ec, channel_ptr which_node,
const std::string& hostname, uint16_t port);
void inbound_channel_stopped(
const std::error_code& ec, channel_ptr which_node);
void subscribe_address(channel_ptr node);
void receive_address_message(const std::error_code& ec,
const address_type& addr, channel_ptr node);
void handle_store_address(const std::error_code& ec);
// fetch methods
void do_fetch_connection_count(
fetch_connection_count_handler handle_fetch);
template <typename Message>
void do_broadcast(const Message& packet, broadcast_handler handle_send)
{
size_t total_nodes = connections_.size() + accepted_channels_.size();
auto send_handler =
std::bind(handle_send, std::placeholders::_1, total_nodes);
for (const connection_info& connection: connections_)
connection.node->send(packet, send_handler);
for (channel_ptr node: accepted_channels_)
node->send(packet, send_handler);
}
io_service::strand strand_;
std::string hosts_filename_ = "hosts";
hosts& hosts_;
handshake& handshake_;
network& network_;
// There's a fixed number of slots that are always trying to reconnect.
size_t max_outbound_ = 8;
connection_list connections_;
// Simply a debugging tool to enforce correct state transition behaviour
// for maintaining connections.
connect_state_list connect_states_;
// Manual connections created by user themselves.
channel_ptr_list manual_connections_;
// Inbound connections from the p2p network.
bool listen_is_enabled_ = true;
channel_ptr_list accepted_channels_;
channel_subscriber_type::ptr channel_subscribe_;
};
} // namespace libbitcoin
#endif
|