44
46
#include "download/available_list.h"
45
47
#include "torrent/peer/client_list.h"
48
#include "torrent/utils/log.h"
50
#include "download_info.h"
47
51
#include "exceptions.h"
48
52
#include "globals.h"
49
53
#include "manager.h"
50
54
#include "peer_info.h"
51
55
#include "peer_list.h"
57
#define LT_LOG_EVENTS(log_fmt, ...) \
58
lt_log_print_info(LOG_PEER_LIST_EVENTS, m_info, "peer_list", log_fmt, __VA_ARGS__);
59
#define LT_LOG_SA_FMT "'%s:%" PRIu16 "'"
53
61
namespace torrent {
55
63
ipv4_table PeerList::m_ipv4_table;
87
99
PeerList::PeerList() :
88
m_availableList(new AvailableList) {
100
m_available_list(new AvailableList) {
91
103
PeerList::~PeerList() {
104
LT_LOG_EVENTS("deleting list total:%" PRIuPTR " available:%" PRIuPTR,
105
size(), m_available_list->size());
92
107
std::for_each(begin(), end(), rak::on(rak::mem_ref(&value_type::second), rak::call_delete<PeerInfo>()));
93
108
base_type::clear();
95
delete m_availableList;
111
delete m_available_list;
115
PeerList::set_info(DownloadInfo* info) {
118
LT_LOG_EVENTS("creating list", 0);
99
122
PeerList::insert_address(const sockaddr* sa, int flags) {
100
if (!socket_address_key::is_comparable(sa))
123
if (!socket_address_key::is_comparable(sa)) {
124
LT_LOG_EVENTS("address not comparable", 0);
128
const rak::socket_address* address = rak::socket_address::cast_from(sa);
103
130
range_type range = base_type::equal_range(sa);
108
135
// What we do depends on the flags, but for now just allow one
109
136
// PeerInfo per address key and do nothing.
110
if (range.first != range.second)
137
if (range.first != range.second) {
138
LT_LOG_EVENTS("address already exists " LT_LOG_SA_FMT,
139
address->address_str().c_str(), address->port());
113
const rak::socket_address* address = rak::socket_address::cast_from(sa);
115
143
PeerInfo* peerInfo = new PeerInfo(sa);
116
144
peerInfo->set_listen_port(address->port());
121
149
base_type::insert(range.second, value_type(socket_address_key(peerInfo->socket_address()), peerInfo));
123
if (flags & address_available && peerInfo->listen_port() != 0)
124
m_availableList->push_back(address);
151
if ((flags & address_available) && peerInfo->listen_port() != 0) {
152
m_available_list->push_back(address);
153
LT_LOG_EVENTS("added available address " LT_LOG_SA_FMT,
154
address->address_str().c_str(), address->port());
156
LT_LOG_EVENTS("added unavailable address " LT_LOG_SA_FMT,
157
address->address_str().c_str(), address->port());
135
169
PeerList::insert_available(const void* al) {
170
const AddressList* addressList = static_cast<const AddressList*>(al);
136
172
uint32_t inserted = 0;
137
const AddressList* addressList = static_cast<const AddressList*>(al);
173
uint32_t invalid = 0;
174
uint32_t unneeded = 0;
175
uint32_t updated = 0;
139
if (m_availableList->size() + addressList->size() > m_availableList->capacity())
140
m_availableList->reserve(m_availableList->size() + addressList->size() + 128);
177
if (m_available_list->size() + addressList->size() > m_available_list->capacity())
178
m_available_list->reserve(m_available_list->size() + addressList->size() + 128);
142
180
// Optimize this so that we don't traverse the tree for every
143
181
// insert, since we know 'al' is sorted.
145
183
AddressList::const_iterator itr = addressList->begin();
146
184
AddressList::const_iterator last = addressList->end();
147
AvailableList::const_iterator availItr = m_availableList->begin();
148
AvailableList::const_iterator availLast = m_availableList->end();
185
AvailableList::const_iterator availItr = m_available_list->begin();
186
AvailableList::const_iterator availLast = m_available_list->end();
150
188
for (; itr != last; itr++) {
151
if (!socket_address_key::is_comparable(itr->c_sockaddr()) || itr->port() == 0)
189
if (!socket_address_key::is_comparable(itr->c_sockaddr()) || itr->port() == 0) {
154
194
availItr = std::find_if(availItr, availLast, rak::bind2nd(std::ptr_fun(&socket_address_less_rak), *itr));
156
196
if (availItr != availLast && !socket_address_less(availItr->c_sockaddr(), itr->c_sockaddr())) {
157
// The address is already in m_availableList, so don't bother
197
// The address is already in m_available_list, so don't bother
158
198
// going further.
174
215
peerInfo->set_port(itr->port());
176
217
if (peerInfo->connection() != NULL ||
177
peerInfo->last_handshake() + 600 > (uint32_t)cachedTime.seconds())
218
peerInfo->last_handshake() + 600 > (uint32_t)cachedTime.seconds()) {
180
223
// If the peer has sent us bad chunks or we just connected or
181
224
// tried to do so a few minutes ago, only update its
188
231
// won't happen often enough to be worth it.
191
m_availableList->push_back(&*itr);
234
m_available_list->push_back(&*itr);
237
LT_LOG_EVENTS("inserted peers"
238
" inserted:%" PRIu32 " invalid:%" PRIu32
239
" unneeded:%" PRIu32 " updated:%" PRIu32
240
" total:%" PRIuPTR " available:%" PRIuPTR,
241
inserted, invalid, unneeded, updated,
242
size(), m_available_list->size());
198
248
PeerList::available_list_size() const {
199
return m_availableList->size();
249
return m_available_list->size();
238
288
if (flags & connect_keep_handshakes &&
239
289
range.first->second->is_handshake() &&
240
290
rak::socket_address::cast_from(range.first->second->socket_address())->port() != address->port())
241
m_availableList->buffer()->push_back(*address);
291
m_available_list->buffer()->push_back(*address);
287
337
if (!itr->second->is_connected())
288
338
throw internal_error("PeerList::disconnected(...) !itr->is_connected().");
340
if (itr->second->transfer_counter() != 0) {
341
// Currently we only log these as it only affects the culling of
343
LT_LOG_EVENTS("disconnected with non-zero transfer counter (%" PRIu32 ") for peer %40s",
344
itr->second->transfer_counter(), itr->second->id_hex());
290
347
itr->second->unset_flags(PeerInfo::flag_connected);
292
349
// Replace the socket address port with the listening port so that
297
354
itr->second->set_last_connection(cachedTime.seconds());
299
356
if (flags & disconnect_available && itr->second->listen_port() != 0)
300
m_availableList->push_back(rak::socket_address::cast_from(itr->second->socket_address()));
357
m_available_list->push_back(rak::socket_address::cast_from(itr->second->socket_address()));
302
359
// Do magic to get rid of unneeded entries.
316
373
for (iterator itr = base_type::begin(); itr != base_type::end(); ) {
317
374
if (itr->second->is_connected() ||
318
itr->second->transfer_counter() != 0 ||
375
itr->second->transfer_counter() != 0 || // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
319
376
itr->second->last_connection() >= timer ||
321
378
(flags & cull_keep_interesting &&
384
// ##################### TODO: LOG CULLING OF PEERS ######################
385
// *** AND STATS OF DISCONNECTING PEERS (the peer info...)...
327
387
// The key is a pointer to a member in the value, although the key
328
388
// shouldn't actually be used in erase (I think), just ot be safe
329
389
// we delete it after erase.