1
// libTorrent - BitTorrent library
2
// Copyright (C) 2005-2007, Jari Sundell
4
// This program is free software; you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation; either version 2 of the License, or
7
// (at your option) any later version.
9
// This program is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
// GNU General Public License for more details.
14
// You should have received a copy of the GNU General Public License
15
// along with this program; if not, write to the Free Software
16
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
// In addition, as a special exception, the copyright holders give
19
// permission to link the code of portions of this program with the
20
// OpenSSL library under certain conditions as described in each
21
// individual source file, and distribute linked combinations
24
// You must obey the GNU General Public License in all respects for
25
// all of the code used other than OpenSSL. If you modify file(s)
26
// with this exception, you may extend this exception to your version
27
// of the file(s), but you are not obligated to do so. If you do not
28
// wish to do so, delete this exception statement from your version.
29
// If you delete this exception statement from all source files in the
30
// program, then also delete it here.
32
// Contact: Jari Sundell <jaris@ifi.uio.no>
35
// 3185 Skoppum, NORWAY
39
#include "torrent/object.h"
41
#include "dht_tracker.h"
46
DhtTracker::add_peer(uint32_t addr, uint16_t port) {
50
SocketAddressCompact compact(addr, port);
52
unsigned int oldest = 0;
53
uint32_t minSeen = ~uint32_t();
55
// Check if peer exists. If not, find oldest peer.
56
for (unsigned int i = 0; i < size(); i++) {
57
if (m_peers[i].peer.addr == compact.addr) {
58
m_peers[i].peer.port = compact.port;
59
m_lastSeen[i] = cachedTime.seconds();
62
} else if (m_lastSeen[i] < minSeen) {
63
minSeen = m_lastSeen[i];
68
// If peer doesn't exist, append to list if the table is not full.
69
if (size() < max_size) {
70
m_peers.push_back(compact);
71
m_lastSeen.push_back(cachedTime.seconds());
73
// Peer doesn't exist and table is full: replace oldest peer.
75
m_peers[oldest] = compact;
76
m_lastSeen[oldest] = cachedTime.seconds();
80
// Return compact info as bencoded string (8 bytes per peer) for up to 30 peers,
81
// returning different peers for each call if there are more.
83
DhtTracker::get_peers(unsigned int maxPeers) {
84
if (sizeof(BencodeAddress) != 8)
85
throw internal_error("DhtTracker::BencodeAddress is packed incorrectly.");
87
PeerList::iterator first = m_peers.begin();
88
PeerList::iterator last = m_peers.end();
90
// If we have more than max_peers, randomly return block of peers.
91
// The peers in overlapping blocks get picked twice as often, but
92
// that's better than returning fewer peers.
93
if (m_peers.size() > maxPeers) {
94
unsigned int blocks = (m_peers.size() + maxPeers - 1) / maxPeers;
96
first += (random() % blocks) * (m_peers.size() - maxPeers) / (blocks - 1);
97
last = first + maxPeers;
100
return raw_list(first->bencode(), last->bencode() - first->bencode());
103
// Remove old announces.
105
DhtTracker::prune(uint32_t maxAge) {
106
uint32_t minSeen = cachedTime.seconds() - maxAge;
108
for (unsigned int i = 0; i < m_lastSeen.size(); i++)
109
if (m_lastSeen[i] < minSeen) m_peers[i].peer.port = 0;
111
m_peers.erase(std::remove_if(m_peers.begin(), m_peers.end(), std::mem_fun_ref(&BencodeAddress::empty)), m_peers.end());
112
m_lastSeen.erase(std::remove_if(m_lastSeen.begin(), m_lastSeen.end(), std::bind2nd(std::less<uint32_t>(), minSeen)), m_lastSeen.end());
114
if (m_peers.size() != m_lastSeen.size())
115
throw internal_error("DhtTracker::prune did inconsistent peer pruning.");