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 #include "config.h"
38 
39 #include <algorithm>
40 #include <functional>
41 #include <cstring>
42 
43 #include "torrent/connection_manager.h"
44 #include "torrent/object.h"
45 #include "torrent/download/choke_group.h"
46 #include "torrent/download/choke_queue.h"
47 
48 #include "exceptions.h"
49 #include "download.h"
50 #include "log.h"
51 #include "option_strings.h"
52 
53 namespace torrent {
54 
55 struct option_single {
56   unsigned int size;
57   const char** name;
58 };
59 
60 struct option_pair {
61   const char*  name;
62   unsigned int value;
63 };
64 
65 option_pair option_list_connection[] = {
66   { "leech",        Download::CONNECTION_LEECH },
67   { "seed",         Download::CONNECTION_SEED },
68   { "initial_seed", Download::CONNECTION_INITIAL_SEED },
69   { "metadata",     Download::CONNECTION_METADATA },
70   { NULL, 0 }
71 };
72 
73 option_pair option_list_heuristics[] = {
74   { "upload_leech",              choke_queue::HEURISTICS_UPLOAD_LEECH },
75   { "upload_leech_experimental", choke_queue::HEURISTICS_UPLOAD_LEECH_EXPERIMENTAL },
76   { "upload_seed",               choke_queue::HEURISTICS_UPLOAD_SEED },
77   { "download_leech",            choke_queue::HEURISTICS_DOWNLOAD_LEECH },
78   { "invalid",                   choke_queue::HEURISTICS_MAX_SIZE },
79   { NULL, 0 }
80 };
81 
82 option_pair option_list_heuristics_download[] = {
83   { "download_leech",            choke_queue::HEURISTICS_DOWNLOAD_LEECH },
84   { NULL, 0 }
85 };
86 
87 option_pair option_list_heuristics_upload[] = {
88   { "upload_leech",              choke_queue::HEURISTICS_UPLOAD_LEECH },
89   { "upload_leech_experimental", choke_queue::HEURISTICS_UPLOAD_LEECH_EXPERIMENTAL },
90   { "upload_seed",               choke_queue::HEURISTICS_UPLOAD_SEED },
91   { NULL, 0 }
92 };
93 
94 option_pair option_list_encryption[] = {
95   { "none",             torrent::ConnectionManager::encryption_none },
96   { "allow_incoming",   torrent::ConnectionManager::encryption_allow_incoming },
97   { "try_outgoing",     torrent::ConnectionManager::encryption_try_outgoing },
98   { "require",          torrent::ConnectionManager::encryption_require },
99   { "require_RC4",      torrent::ConnectionManager::encryption_require_RC4 },
100   { "require_rc4",      torrent::ConnectionManager::encryption_require_RC4 },
101   { "enable_retry",     torrent::ConnectionManager::encryption_enable_retry },
102   { "prefer_plaintext", torrent::ConnectionManager::encryption_prefer_plaintext },
103   { NULL, 0 }
104 };
105 
106 option_pair option_list_ip_filter[] = {
107   { "unwanted",  PeerInfo::flag_unwanted },
108   { "preferred", PeerInfo::flag_preferred },
109   { NULL, 0 }
110 };
111 
112 option_pair option_list_ip_tos[] = {
113   { "default",     torrent::ConnectionManager::iptos_default },
114   { "lowdelay",    torrent::ConnectionManager::iptos_lowdelay },
115   { "throughput",  torrent::ConnectionManager::iptos_throughput },
116   { "reliability", torrent::ConnectionManager::iptos_reliability },
117   { "mincost",     torrent::ConnectionManager::iptos_mincost },
118   { NULL, 0 }
119 };
120 
121 option_pair option_list_tracker_mode[] = {
122   { "normal",     choke_group::TRACKER_MODE_NORMAL },
123   { "aggressive", choke_group::TRACKER_MODE_AGGRESSIVE },
124   { NULL, 0 }
125 };
126 
127 const char* option_list_log_group[] = {
128   "critical",
129   "error",
130   "warn",
131   "notice",
132   "info",
133   "debug",
134 
135   "connection_critical",
136   "connection_error",
137   "connection_warn",
138   "connection_notice",
139   "connection_info",
140   "connection_debug",
141 
142   "dht_critical",
143   "dht_error",
144   "dht_warn",
145   "dht_notice",
146   "dht_info",
147   "dht_debug",
148 
149   "peer_critical",
150   "peer_error",
151   "peer_warn",
152   "peer_notice",
153   "peer_info",
154   "peer_debug",
155 
156   "socket_critical",
157   "socket_error",
158   "socket_warn",
159   "socket_notice",
160   "socket_info",
161   "socket_debug",
162 
163   "storage_critical",
164   "storage_error",
165   "storage_warn",
166   "storage_notice",
167   "storage_info",
168   "storage_debug",
169 
170   "thread_critical",
171   "thread_error",
172   "thread_warn",
173   "thread_notice",
174   "thread_info",
175   "thread_debug",
176 
177   "tracker_critical",
178   "tracker_error",
179   "tracker_warn",
180   "tracker_notice",
181   "tracker_info",
182   "tracker_debug",
183 
184   "torrent_critical",
185   "torrent_error",
186   "torrent_warn",
187   "torrent_notice",
188   "torrent_info",
189   "torrent_debug",
190 
191   "__non_cascading__",
192 
193   "dht_all",
194   "dht_manager",
195   "dht_node",
196   "dht_router",
197   "dht_server",
198 
199   "instrumentation_memory",
200   "instrumentation_mincore",
201   "instrumentation_choke",
202   "instrumentation_polling",
203   "instrumentation_transfers",
204 
205   "peer_list_events",
206 
207   "protocol_piece_events",
208   "protocol_metadata_events",
209   "protocol_network_errors",
210   "protocol_storage_errors",
211 
212   "resume_data",
213 
214   "rpc_events",
215   "rpc_dump",
216 
217   "ui_events",
218 
219   NULL
220 };
221 
222 const char* option_list_tracker_event[] = {
223   "updated",
224   "completed",
225   "started",
226   "stopped",
227   "scrape",
228 
229   NULL
230 };
231 
232 option_pair* option_pair_lists[OPTION_START_COMPACT] = {
233   option_list_connection,
234   option_list_heuristics,
235   option_list_heuristics_download,
236   option_list_heuristics_upload,
237   option_list_encryption,
238   option_list_ip_filter,
239   option_list_ip_tos,
240   option_list_tracker_mode,
241 };
242 
243 #define OPTION_SINGLE_ENTRY(single_name) \
244   { sizeof(single_name) / sizeof(const char*) - 1, single_name }
245 
246 option_single option_single_lists[OPTION_SINGLE_SIZE] = {
247   OPTION_SINGLE_ENTRY(option_list_log_group),
248   OPTION_SINGLE_ENTRY(option_list_tracker_event),
249 };
250 
251 int
option_find_string(option_enum opt_enum,const char * name)252 option_find_string(option_enum opt_enum, const char* name) {
253   if (opt_enum < OPTION_START_COMPACT) {
254     option_pair* itr = option_pair_lists[opt_enum];
255 
256     do {
257       if (std::strcmp(itr->name, name) == 0)
258         return itr->value;
259     } while ((++itr)->name != NULL);
260 
261   } else if (opt_enum < OPTION_MAX_SIZE) {
262     const char** itr = option_single_lists[opt_enum - OPTION_START_COMPACT].name;
263 
264     do {
265       if (std::strcmp(*itr, name) == 0)
266         return std::distance(option_single_lists[opt_enum - OPTION_START_COMPACT].name, itr);
267     } while (*++itr != NULL);
268   }
269 
270   throw input_error("Invalid option name.");
271 }
272 
273 const char*
option_as_string(option_enum opt_enum,unsigned int value)274 option_as_string(option_enum opt_enum, unsigned int value) {
275   if (opt_enum < OPTION_START_COMPACT) {
276     option_pair* itr = option_pair_lists[opt_enum];
277 
278     do {
279       if (itr->value == value)
280         return itr->name;
281     } while ((++itr)->name != NULL);
282 
283   } else if (opt_enum < OPTION_MAX_SIZE) {
284     if (value < option_single_lists[opt_enum - OPTION_START_COMPACT].size)
285       return option_single_lists[opt_enum - OPTION_START_COMPACT].name[value];
286   }
287 
288   throw input_error("Invalid option value.");
289 }
290 
291 torrent::Object
option_list_strings(option_enum opt_enum)292 option_list_strings(option_enum opt_enum) {
293   Object::list_type result;
294 
295   if (opt_enum < OPTION_START_COMPACT) {
296     option_pair* itr = option_pair_lists[opt_enum];
297 
298     while (itr->name != NULL)
299       result.push_back(std::string(itr++->name));
300 
301   } else if (opt_enum < OPTION_MAX_SIZE) {
302     const char** itr = option_single_lists[opt_enum - OPTION_START_COMPACT].name;
303 
304     while (*itr != NULL) result.push_back(std::string(*itr++));
305   }
306 
307   return Object::from_list(result);
308 }
309 
310 }
311