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