1 // libTorrent - BitTorrent library
2 // Copyright (C) 2005-2011, Jari Sundell
3 //
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.
8 //
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.
13 //
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
17 //
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
22 // including the two.
23 //
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.
31 //
32 // Contact:  Jari Sundell <jaris@ifi.uio.no>
33 //
34 //           Skomakerveien 33
35 //           3185 Skoppum, NORWAY
36 
37 #ifndef LIBTORRENT_TRACKER_LIST_H
38 #define LIBTORRENT_TRACKER_LIST_H
39 
40 #include <algorithm>
41 #include <string>
42 #include <vector>
43 #include <torrent/common.h>
44 #include lt_tr1_functional
45 
46 namespace torrent {
47 
48 class AddressList;
49 class DownloadInfo;
50 class DownloadWrapper;
51 class Tracker;
52 
53 // The tracker list will contain a list of tracker, divided into
54 // subgroups. Each group must be randomized before we start. When
55 // starting the tracker request, always start from the beginning and
56 // iterate if the request failed. Upon request success move the
57 // tracker to the beginning of the subgroup and start from the
58 // beginning of the whole list.
59 
60 class LIBTORRENT_EXPORT TrackerList : private std::vector<Tracker*> {
61 public:
62   friend class DownloadWrapper;
63 
64   typedef std::vector<Tracker*> base_type;
65   typedef AddressList           address_list;
66 
67   typedef std::function<void (Tracker*)>                     slot_tracker;
68   typedef std::function<void (Tracker*, const std::string&)> slot_string;
69   typedef std::function<uint32_t (Tracker*, AddressList*)>   slot_address_list;
70 
71   using base_type::value_type;
72 
73   using base_type::iterator;
74   using base_type::const_iterator;
75   using base_type::reverse_iterator;
76   using base_type::const_reverse_iterator;
77   using base_type::size;
78   using base_type::empty;
79 
80   using base_type::begin;
81   using base_type::end;
82   using base_type::rbegin;
83   using base_type::rend;
84   using base_type::front;
85   using base_type::back;
86 
87   using base_type::at;
88   using base_type::operator[];
89 
90   TrackerList();
91 
92   bool                has_active() const;
93   bool                has_active_not_scrape() const;
94   bool                has_active_in_group(uint32_t group) const;
95   bool                has_active_not_scrape_in_group(uint32_t group) const;
96   bool                has_usable() const;
97 
98   unsigned int        count_active() const;
99   unsigned int        count_usable() const;
100 
close_all()101   void                close_all() { close_all_excluding(0); }
102   void                close_all_excluding(int event_bitmap);
103 
104   void                disown_all_including(int event_bitmap);
105 
106   void                clear();
107   void                clear_stats();
108 
109   iterator            insert(unsigned int group, Tracker* tracker);
110   void                insert_url(unsigned int group, const std::string& url, bool extra_tracker = false);
111 
112   void                send_state(Tracker* tracker, int new_event);
113   void                send_state_idx(unsigned idx, int new_event);
114   void                send_state_itr(iterator itr, int new_event);
115 
116   void                send_scrape(Tracker* tracker);
117 
info()118   DownloadInfo*       info()                                  { return m_info; }
state()119   int                 state()                                 { return m_state; }
120 
key()121   uint32_t            key() const                             { return m_key; }
set_key(uint32_t key)122   void                set_key(uint32_t key)                   { m_key = key; }
123 
numwant()124   int32_t             numwant() const                         { return m_numwant; }
set_numwant(int32_t n)125   void                set_numwant(int32_t n)                  { m_numwant = n; }
126 
find(Tracker * tb)127   iterator            find(Tracker* tb)                       { return std::find(begin(), end(), tb); }
128   iterator            find_url(const std::string& url);
129 
130   iterator            find_usable(iterator itr);
131   const_iterator      find_usable(const_iterator itr) const;
132 
133   iterator            find_next_to_request(iterator itr);
134 
135   iterator            begin_group(unsigned int group);
136   const_iterator      begin_group(unsigned int group) const;
end_group(unsigned int group)137   iterator            end_group(unsigned int group)           { return begin_group(group + 1); }
end_group(unsigned int group)138   const_iterator      end_group(unsigned int group) const     { return begin_group(group + 1); }
139 
140   size_type           size_group() const;
141   void                cycle_group(unsigned int group);
142 
143   iterator            promote(iterator itr);
144   void                randomize_group_entries();
145 
146   void                receive_success(Tracker* tb, AddressList* l);
147   void                receive_failed(Tracker* tb, const std::string& msg);
148 
149   void                receive_scrape_success(Tracker* tb);
150   void                receive_scrape_failed(Tracker* tb, const std::string& msg);
151 
152   // Used by libtorrent internally.
slot_success()153   slot_address_list&  slot_success()                          { return m_slot_success; }
slot_failure()154   slot_string&        slot_failure()                          { return m_slot_failed; }
155 
slot_scrape_success()156   slot_tracker&       slot_scrape_success()                   { return m_slot_scrape_success; }
slot_scrape_failure()157   slot_string&        slot_scrape_failure()                   { return m_slot_scrape_failed; }
158 
slot_tracker_enabled()159   slot_tracker&       slot_tracker_enabled()                  { return m_slot_tracker_enabled; }
slot_tracker_disabled()160   slot_tracker&       slot_tracker_disabled()                 { return m_slot_tracker_disabled; }
161 
162 protected:
set_info(DownloadInfo * info)163   void                set_info(DownloadInfo* info)            { m_info = info; }
164 
set_state(int s)165   void                set_state(int s)                        { m_state = s; }
166 
167 private:
168   TrackerList(const TrackerList&) LIBTORRENT_NO_EXPORT;
169   void operator = (const TrackerList&) LIBTORRENT_NO_EXPORT;
170 
171   DownloadInfo*       m_info;
172   int                 m_state;
173 
174   uint32_t            m_key;
175   int32_t             m_numwant;
176 
177   slot_address_list   m_slot_success;
178   slot_string         m_slot_failed;
179 
180   slot_tracker        m_slot_scrape_success;
181   slot_string         m_slot_scrape_failed;
182 
183   slot_tracker        m_slot_tracker_enabled;
184   slot_tracker        m_slot_tracker_disabled;
185 };
186 
187 inline void
send_state_idx(unsigned idx,int new_event)188 TrackerList::send_state_idx(unsigned idx, int new_event) {
189   send_state(at(idx), new_event);
190 }
191 
192 inline void
send_state_itr(iterator itr,int new_event)193 TrackerList::send_state_itr(iterator itr, int new_event) {
194   if (itr == end())
195     return;
196 
197   send_state(*itr, new_event);
198 }
199 
200 }
201 
202 #endif
203