Skip to content

Commit 32700ab

Browse files
authored
Merge pull request #193 from thecodefactory/seed-address-response
Implement get_address message response
2 parents 731e49b + 21abea2 commit 32700ab

8 files changed

Lines changed: 64 additions & 20 deletions

File tree

include/bitcoin/network/hosts.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class BCT_API hosts
5555

5656
virtual size_t count() const;
5757
virtual code fetch(address& out) const;
58+
virtual code fetch(address::list& out) const;
5859
virtual code remove(const address& host);
5960
virtual code store(const address& host);
6061
virtual void store(const address::list& hosts, result_handler handler);
@@ -65,6 +66,8 @@ class BCT_API hosts
6566

6667
iterator find(const address& host);
6768

69+
const size_t capacity_;
70+
6871
// These are protected by a mutex.
6972
list buffer_;
7073
std::atomic<bool> stopped_;

include/bitcoin/network/p2p.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,9 @@ class BCT_API p2p
168168
/// Get a randomly-selected address.
169169
virtual code fetch_address(address& out_address) const;
170170

171+
/// Get a list of stored hosts
172+
virtual code fetch_addresses(address::list& out_addresses) const;
173+
171174
/// Remove an address.
172175
virtual code remove(const address& address);
173176

src/channel.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ using namespace std::placeholders;
3737
// Factory for deadline timer pointer construction.
3838
static deadline::ptr alarm(threadpool& pool, const asio::duration& duration)
3939
{
40-
return std::make_shared<deadline>(pool, pseudo_randomize(duration));
40+
return std::make_shared<deadline>(pool, pseudo_random::duration(duration));
4141
}
4242

4343
channel::channel(threadpool& pool, socket::ptr socket,

src/hosts.cpp

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,12 @@ using namespace bc::config;
3434

3535
// TODO: change to network_address bimap hash table with services and age.
3636
hosts::hosts(const settings& settings)
37-
: buffer_(std::max(settings.host_pool_capacity, 1u)),
37+
: capacity_(std::min(max_address, static_cast<size_t>(
38+
settings.host_pool_capacity))),
39+
buffer_(std::max(capacity_, static_cast<size_t>(1u))),
3840
stopped_(true),
3941
file_path_(settings.hosts_file),
40-
disabled_(settings.host_pool_capacity == 0)
42+
disabled_(capacity_ == 0)
4143
{
4244
}
4345

@@ -78,13 +80,45 @@ code hosts::fetch(address& out) const
7880
return error::not_found;
7981

8082
// Randomly select an address from the buffer.
81-
const auto random = pseudo_random(0, buffer_.size() - 1);
83+
const auto random = pseudo_random::next(0, buffer_.size() - 1);
8284
const auto index = static_cast<size_t>(random);
8385
out = buffer_[index];
8486
return error::success;
8587
///////////////////////////////////////////////////////////////////////////
8688
}
8789

90+
code hosts::fetch(address::list& out) const
91+
{
92+
if (disabled_)
93+
return error::not_found;
94+
95+
// Critical Section
96+
///////////////////////////////////////////////////////////////////////////
97+
{
98+
shared_lock lock(mutex_);
99+
100+
if (stopped_)
101+
return error::service_stopped;
102+
103+
if (buffer_.empty())
104+
return error::not_found;
105+
106+
const auto out_count = std::min(buffer_.size(), capacity_) /
107+
static_cast<size_t>(pseudo_random::next(1, 20));
108+
109+
if (out_count == 0)
110+
return error::success;
111+
112+
out.reserve(out_count);
113+
for (size_t index = 0; index < out_count; ++index)
114+
out.push_back(buffer_[index]);
115+
}
116+
///////////////////////////////////////////////////////////////////////////
117+
118+
pseudo_random::shuffle(out);
119+
return error::success;
120+
}
121+
88122
// load
89123
code hosts::start()
90124
{
@@ -288,7 +322,7 @@ void hosts::store(const address::list& hosts, result_handler handler)
288322
// Accept between 1 and all of this peer's addresses up to capacity.
289323
const auto capacity = buffer_.capacity();
290324
const auto usable = std::min(hosts.size(), capacity);
291-
const auto random = static_cast<size_t>(pseudo_random(1, usable));
325+
const auto random = static_cast<size_t>(pseudo_random::next(1, usable));
292326

293327
// But always accept at least the amount we are short if available.
294328
const auto gap = capacity - buffer_.size();

src/p2p.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,11 @@ code p2p::fetch_address(address& out_address) const
420420
return hosts_.fetch(out_address);
421421
}
422422

423+
code p2p::fetch_addresses(address::list& out_addresses) const
424+
{
425+
return hosts_.fetch(out_addresses);
426+
}
427+
423428
code p2p::remove(const address& address)
424429
{
425430
return hosts_.remove(address);

src/protocols/protocol_address_31402.cpp

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -102,22 +102,21 @@ bool protocol_address_31402::handle_receive_get_address(const code& ec,
102102
if (stopped(ec))
103103
return false;
104104

105-
// TODO: allowing repeated queries can allow a channel to map our history.
106-
// TODO: pull active hosts from host cache (currently just resending self).
107-
// TODO: need to distort for privacy, don't send currently-connected peers.
108-
// TODO: response size limit is max_address (1000).
105+
bc::message::network_address::list addresses;
106+
network_.fetch_addresses(addresses);
109107

110-
if (self_.addresses().empty())
111-
return false;
112-
113-
LOG_DEBUG(LOG_NETWORK)
114-
<< "Sending addresses to [" << authority() << "] ("
115-
<< self_.addresses().size() << ")";
108+
if (!addresses.empty())
109+
{
110+
const address address_subset(addresses);
111+
SEND2(address_subset, handle_send, _1, self_.command);
116112

117-
SEND2(self_, handle_send, _1, self_.command);
113+
LOG_DEBUG(LOG_NETWORK)
114+
<< "Sending addresses to [" << authority() << "] ("
115+
<< self_.addresses().size() << ")";
116+
}
118117

119-
// RESUBSCRIBE
120-
return true;
118+
// do not resubscribe; one response per connection permitted
119+
return false;
121120
}
122121

123122
void protocol_address_31402::handle_store_addresses(const code& ec)

src/protocols/protocol_ping_60001.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ void protocol_ping_60001::send_ping(const code& ec)
6767
}
6868

6969
pending_ = true;
70-
const auto nonce = pseudo_random();
70+
const auto nonce = pseudo_random::next();
7171
SUBSCRIBE3(pong, handle_receive_pong, _1, _2, nonce);
7272
SEND2(ping{ nonce }, handle_send_ping, _1, ping::command);
7373
}

src/sessions/session.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ void session::start_channel(channel::ptr channel,
196196
result_handler handle_started)
197197
{
198198
channel->set_notify(notify_on_connect_);
199-
channel->set_nonce(pseudo_random(1, max_uint64));
199+
channel->set_nonce(pseudo_random::next(1, max_uint64));
200200

201201
// The channel starts, invokes the handler, then starts the read cycle.
202202
channel->start(

0 commit comments

Comments
 (0)