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
40
#include <rak/functional.h>
41
#include <rak/string_manip.h>
43
#include "client_list.h"
44
#include "exceptions.h"
45
#include "hash_string.h"
49
ClientList::ClientList() {
50
insert(ClientInfo::TYPE_UNKNOWN, NULL, NULL, NULL);
52
// Move this to a seperate initialize function in libtorrent.
54
// Sorted by popularity to optimize search. This list is heavily
55
// biased by my own prejudices, and not at all based on facts.
57
// First batch of clients.
58
insert_helper(ClientInfo::TYPE_AZUREUS, "AZ", NULL, NULL, "Azureus");
59
insert_helper(ClientInfo::TYPE_AZUREUS, "BC", NULL, NULL, "BitComet");
60
insert_helper(ClientInfo::TYPE_AZUREUS, "CD", NULL, NULL, "Enhanced CTorrent");
61
insert_helper(ClientInfo::TYPE_AZUREUS, "KT", NULL, NULL, "KTorrent");
62
insert_helper(ClientInfo::TYPE_AZUREUS, "LT", NULL, NULL, "libtorrent");
63
insert_helper(ClientInfo::TYPE_AZUREUS, "lt", NULL, NULL, "libTorrent");
64
insert_helper(ClientInfo::TYPE_AZUREUS, "UT", NULL, NULL, "uTorrent");
66
insert_helper(ClientInfo::TYPE_MAINLINE, "M", NULL, NULL, "Mainline");
68
insert_helper(ClientInfo::TYPE_COMPACT, "T", NULL, NULL, "BitTornado");
70
// Second batch of clients.
71
insert_helper(ClientInfo::TYPE_AZUREUS, "AR", NULL, NULL, "Arctic");
72
insert_helper(ClientInfo::TYPE_AZUREUS, "BB", NULL, NULL, "BitBuddy");
73
insert_helper(ClientInfo::TYPE_AZUREUS, "BX", NULL, NULL, "Bittorrent X");
74
insert_helper(ClientInfo::TYPE_AZUREUS, "BS", NULL, NULL, "BTSlave");
75
insert_helper(ClientInfo::TYPE_AZUREUS, "CT", NULL, NULL, "CTorrent");
76
insert_helper(ClientInfo::TYPE_AZUREUS, "DE", NULL, NULL, "DelugeTorrent");
77
insert_helper(ClientInfo::TYPE_AZUREUS, "ES", NULL, NULL, "Electric Sheep");
78
insert_helper(ClientInfo::TYPE_AZUREUS, "LP", NULL, NULL, "Lphant");
79
insert_helper(ClientInfo::TYPE_AZUREUS, "MT", NULL, NULL, "MoonlightTorrent");
80
insert_helper(ClientInfo::TYPE_AZUREUS, "MP", NULL, NULL, "MooPolice");
81
insert_helper(ClientInfo::TYPE_AZUREUS, "QT", NULL, NULL, "Qt 4 Torrent");
82
insert_helper(ClientInfo::TYPE_AZUREUS, "RT", NULL, NULL, "Retriever");
83
insert_helper(ClientInfo::TYPE_AZUREUS, "SZ", NULL, NULL, "Shareaza");
84
insert_helper(ClientInfo::TYPE_AZUREUS, "SS", NULL, NULL, "SwarmScope");
85
insert_helper(ClientInfo::TYPE_AZUREUS, "SB", NULL, NULL, "Swiftbit");
86
insert_helper(ClientInfo::TYPE_AZUREUS, "TN", NULL, NULL, "TorrentDotNET");
87
insert_helper(ClientInfo::TYPE_AZUREUS, "TS", NULL, NULL, "Torrentstorm");
88
insert_helper(ClientInfo::TYPE_AZUREUS, "TR", NULL, NULL, "Transmission");
89
insert_helper(ClientInfo::TYPE_AZUREUS, "XT", NULL, NULL, "XanTorrent");
90
insert_helper(ClientInfo::TYPE_AZUREUS, "ZT", NULL, NULL, "ZipTorrent");
92
insert_helper(ClientInfo::TYPE_COMPACT, "A", NULL, NULL, "ABC");
93
insert_helper(ClientInfo::TYPE_COMPACT, "S", NULL, NULL, "Shadow's client");
94
insert_helper(ClientInfo::TYPE_COMPACT, "U", NULL, NULL, "UPnP NAT BitTorrent");
95
insert_helper(ClientInfo::TYPE_COMPACT, "O", NULL, NULL, "Osprey Permaseed");
97
// Third batch of clients.
98
insert_helper(ClientInfo::TYPE_AZUREUS, "AX", NULL, NULL, "BitPump");
99
insert_helper(ClientInfo::TYPE_AZUREUS, "BF", NULL, NULL, "BitFlu");
100
insert_helper(ClientInfo::TYPE_AZUREUS, "BG", NULL, NULL, "BTG");
101
insert_helper(ClientInfo::TYPE_AZUREUS, "BR", NULL, NULL, "BitRocket");
102
insert_helper(ClientInfo::TYPE_AZUREUS, "EB", NULL, NULL, "EBit");
103
insert_helper(ClientInfo::TYPE_AZUREUS, "HL", NULL, NULL, "Halite");
104
insert_helper(ClientInfo::TYPE_AZUREUS, "qB", NULL, NULL, "qBittorrent");
105
insert_helper(ClientInfo::TYPE_AZUREUS, "UL", NULL, NULL, "uLeecher!");
106
insert_helper(ClientInfo::TYPE_AZUREUS, "XL", NULL, NULL, "XeiLun");
108
insert_helper(ClientInfo::TYPE_COMPACT, "R", NULL, NULL, "Tribler");
111
ClientList::~ClientList() {
112
for (iterator itr = begin(), last = end(); itr != last; ++itr)
117
ClientList::insert(ClientInfo::id_type type, const char* key, const char* version, const char* upperVersion) {
118
if (type >= ClientInfo::TYPE_MAX_SIZE)
119
throw input_error("Invalid client info id type.");
121
ClientInfo clientInfo;
123
clientInfo.set_type(type);
124
clientInfo.set_info(new ClientInfo::info_type);
125
clientInfo.set_short_description("Unknown");
127
std::memset(clientInfo.mutable_key(), 0, ClientInfo::max_key_size);
130
std::memset(clientInfo.mutable_key(), 0, ClientInfo::max_key_size);
132
std::strncpy(clientInfo.mutable_key(), key, ClientInfo::max_key_size);
135
std::memcpy(clientInfo.mutable_version(), version, ClientInfo::max_version_size);
137
std::memset(clientInfo.mutable_version(), 0, ClientInfo::max_version_size);
139
if (upperVersion != NULL)
140
std::memcpy(clientInfo.mutable_upper_version(), upperVersion, ClientInfo::max_version_size);
142
std::memset(clientInfo.mutable_upper_version(), -1, ClientInfo::max_version_size);
144
return base_type::insert(end(), clientInfo);
148
ClientList::insert_helper(ClientInfo::id_type type,
151
const char* upperVersion,
152
const char* shortDescription) {
153
char newKey[ClientInfo::max_key_size];
155
std::memset(newKey, 0, ClientInfo::max_key_size);
156
std::memcpy(newKey, key, ClientInfo::key_size(type));
158
iterator itr = insert(type, newKey, version, upperVersion);
159
itr->set_short_description(shortDescription);
164
// Make this properly honor const-ness.
166
ClientList::retrieve_id(ClientInfo* dest, const HashString& id) const {
167
if (id[0] == '-' && id[7] == '-' &&
168
std::isalpha(id[1]) && std::isalpha(id[2]) &&
169
std::isxdigit(id[3]) && std::isxdigit(id[4]) && std::isxdigit(id[5]) && std::isxdigit(id[6])) {
170
dest->set_type(ClientInfo::TYPE_AZUREUS);
172
dest->mutable_key()[0] = id[1];
173
dest->mutable_key()[1] = id[2];
175
for (int i = 0; i < 4; i++)
176
dest->mutable_version()[i] = dest->mutable_upper_version()[i] = rak::hexchar_to_value(id[3 + i]);
178
} else if (std::isalpha(id[0]) && id[4] == '-' &&
179
std::isxdigit(id[1]) && std::isxdigit(id[2]) && std::isxdigit(id[3])) {
180
dest->set_type(ClientInfo::TYPE_COMPACT);
182
dest->mutable_key()[0] = id[0];
183
dest->mutable_key()[1] = '\0';
185
dest->mutable_version()[0] = dest->mutable_upper_version()[0] = rak::hexchar_to_value(id[1]);
186
dest->mutable_version()[1] = dest->mutable_upper_version()[1] = rak::hexchar_to_value(id[2]);
187
dest->mutable_version()[2] = dest->mutable_upper_version()[2] = rak::hexchar_to_value(id[3]);
188
dest->mutable_version()[3] = dest->mutable_upper_version()[3] = '\0';
190
} else if (std::isalpha(id[0]) && std::isdigit(id[1]) && id[2] == '-' &&
191
std::isdigit(id[3]) && (id[6] == '-' || id[7] == '-')) {
193
dest->set_type(ClientInfo::TYPE_MAINLINE);
195
dest->mutable_key()[0] = id[0];
196
dest->mutable_key()[1] = '\0';
198
dest->mutable_version()[0] = dest->mutable_upper_version()[0] = rak::hexchar_to_value(id[1]);
200
if (id[4] == '-' && std::isdigit(id[5]) && id[6] == '-') {
201
dest->mutable_version()[1] = dest->mutable_upper_version()[1] = rak::hexchar_to_value(id[3]);
202
dest->mutable_version()[2] = dest->mutable_upper_version()[2] = rak::hexchar_to_value(id[5]);
203
dest->mutable_version()[3] = dest->mutable_upper_version()[3] = '\0';
205
} else if (std::isdigit(id[4]) && id[5] == '-' && std::isdigit(id[6]) && id[7] == '-') {
206
dest->mutable_version()[1] = dest->mutable_upper_version()[1] = rak::hexchar_to_value(id[3]) * 10 + rak::hexchar_to_value(id[4]);
207
dest->mutable_version()[2] = dest->mutable_upper_version()[2] = rak::hexchar_to_value(id[6]);
208
dest->mutable_version()[3] = dest->mutable_upper_version()[3] = '\0';
212
std::memset(dest->mutable_upper_version(), 0, ClientInfo::max_version_size);
218
// And then the incompatible idiots that make life difficult for us
219
// others. (There's '3' schemes to choose from already...)
223
// The first entry always contains the default ClientInfo.
225
std::memset(dest->mutable_upper_version(), 0, ClientInfo::max_version_size);
230
const_iterator itr = std::find_if(begin() + 1, end(), rak::bind1st(std::ptr_fun(&ClientInfo::intersects), *dest));
233
dest->set_info(begin()->info());
235
dest->set_info(itr->info());
241
ClientList::retrieve_unknown(ClientInfo* dest) const {
243
std::memset(dest->mutable_upper_version(), 0, ClientInfo::max_version_size);