summaryrefslogtreecommitdiffstats
path: root/src/worker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/worker.cpp')
-rw-r--r--src/worker.cpp481
1 files changed, 266 insertions, 215 deletions
diff --git a/src/worker.cpp b/src/worker.cpp
index 7f0203f..4f473c6 100644
--- a/src/worker.cpp
+++ b/src/worker.cpp
@@ -29,7 +29,8 @@
#include <boost/iostreams/filter/gzip.hpp>
//---------- Worker - does stuff with input
-worker::worker(torrent_list &torrents, user_list &users, std::vector<std::string> &_whitelist, config * conf_obj, mysql * db_obj, site_comm &sc) : torrents_list(torrents), users_list(users), whitelist(_whitelist), conf(conf_obj), db(db_obj), s_comm(sc) {
+worker::worker(torrent_list &torrents, user_list &users, std::vector<std::string> &_whitelist, config * conf_obj, mysql * db_obj, site_comm * sc) : torrents_list(torrents), users_list(users), whitelist(_whitelist), conf(conf_obj), db(db_obj), s_comm(sc)
+{
status = OPEN;
}
bool worker::signal(int sig) {
@@ -46,103 +47,113 @@ bool worker::signal(int sig) {
}
std::string worker::work(std::string &input, std::string &ip, bool &gzip) {
unsigned int input_length = input.length();
-
+
//---------- Parse request - ugly but fast. Using substr exploded.
- if(input_length < 60) { // Way too short to be anything useful
+ if (input_length < 60) { // Way too short to be anything useful
return error("GET string too short");
}
-
- size_t pos = 5; // skip GET /
-
+
+ size_t pos = 5; // skip 'GET /'
+
// Get the passkey
std::string passkey;
passkey.reserve(32);
- if(input[37] != '/') {
+ if (input[37] != '/') {
+ /* This didn't work as intended. We want the crawler to download the meta tag
+ if (input.substr(5, 10) == "robots.txt") {
+ // Let's just hope that no crawler has a / at pos 37
+ return "User-agent: *\nDisallow: /";
+ }*/
return error("Malformed announce");
}
-
- for(; pos < 37; pos++) {
+
+ for (; pos < 37; pos++) {
passkey.push_back(input[pos]);
}
-
+
pos = 38;
-
+
// Get the action
enum action_t {
INVALID = 0, ANNOUNCE, SCRAPE, UPDATE
};
action_t action = INVALID;
-
- switch(input[pos]) {
+
+ switch (input[pos]) {
case 'a':
action = ANNOUNCE;
- pos += 9;
+ pos += 8;
break;
case 's':
action = SCRAPE;
- pos += 7;
+ pos += 6;
break;
case 'u':
action = UPDATE;
- pos += 7;
+ pos += 6;
break;
}
- if(action == INVALID) {
+ if (action == INVALID) {
return error("invalid action");
}
+ if (input[pos] != '?') {
+ // No parameters given. Probably means we're not talking to a torrent client
+ return "<html><head><meta name=\"robots\" content=\"noindex, nofollow\" /></head><body>Nothing to see here</body></html>";
+ }
+
if ((status != OPEN) && (action != UPDATE)) {
return error("The tracker is temporarily unavailable.");
}
-
+
// Parse URL params
std::list<std::string> infohashes; // For scrape only
-
+
std::map<std::string, std::string> params;
std::string key;
std::string value;
bool parsing_key = true; // true = key, false = value
-
- for(; pos < input_length; ++pos) {
- if(input[pos] == '=') {
+
+ pos++; // Skip the '?'
+ for (; pos < input_length; ++pos) {
+ if (input[pos] == '=') {
parsing_key = false;
- } else if(input[pos] == '&' || input[pos] == ' ') {
+ } else if (input[pos] == '&' || input[pos] == ' ') {
parsing_key = true;
- if(action == SCRAPE && key == "info_hash") {
+ if (action == SCRAPE && key == "info_hash") {
infohashes.push_back(value);
} else {
-
params[key] = value;
}
key.clear();
value.clear();
- if(input[pos] == ' ') {
+ if (input[pos] == ' ') {
break;
}
} else {
- if(parsing_key) {
+ if (parsing_key) {
key.push_back(input[pos]);
} else {
value.push_back(input[pos]);
}
}
}
-
- pos += 10; // skip HTTP/1.1 - should probably be +=11, but just in case a client doesn't send \r
-
+
+ pos += 10; // skip 'HTTP/1.1' - should probably be +=11, but just in case a client doesn't send \r
+
// Parse headers
std::map<std::string, std::string> headers;
parsing_key = true;
bool found_data = false;
-
- for(; pos < input_length; ++pos) {
- if(input[pos] == ':') {
+
+ for (; pos < input_length; ++pos) {
+ if (input[pos] == ':') {
parsing_key = false;
++pos; // skip space after :
- } else if(input[pos] == '\n' || input[pos] == '\r') {
+ } else if (input[pos] == '\n' || input[pos] == '\r') {
parsing_key = true;
-
- if(found_data) {
+
+ if (found_data) {
found_data = false; // dodge for getting around \r\n or just \n
std::transform(key.begin(), key.end(), key.begin(), ::tolower);
headers[key] = value;
@@ -151,38 +162,38 @@ std::string worker::work(std::string &input, std::string &ip, bool &gzip) {
}
} else {
found_data = true;
- if(parsing_key) {
+ if (parsing_key) {
key.push_back(input[pos]);
} else {
value.push_back(input[pos]);
}
}
}
-
-
-
- if(action == UPDATE) {
- if(passkey == conf->site_password) {
+
+
+
+ if (action == UPDATE) {
+ if (passkey == conf->site_password) {
return update(params);
} else {
return error("Authentication failure");
}
}
-
+
// Either a scrape or an announce
-
+
user_list::iterator u = users_list.find(passkey);
- if(u == users_list.end()) {
+ if (u == users_list.end()) {
return error("Passkey not found");
}
-
- if(action == ANNOUNCE) {
+
+ if (action == ANNOUNCE) {
boost::mutex::scoped_lock lock(db->torrent_list_mutex);
// Let's translate the infohash into something nice
// info_hash is a url encoded (hex) base 20 number
std::string info_hash_decoded = hex_decode(params["info_hash"]);
torrent_list::iterator tor = torrents_list.find(info_hash_decoded);
- if(tor == torrents_list.end()) {
+ if (tor == torrents_list.end()) {
boost::mutex::scoped_lock lock(del_reasons_lock);
auto msg = del_reasons.find(info_hash_decoded);
if (msg != del_reasons.end()) {
@@ -210,55 +221,73 @@ std::string worker::error(std::string err) {
return output;
}
-std::string worker::announce(torrent &tor, user &u, std::map<std::string, std::string> &params, std::map<std::string, std::string> &headers, std::string &ip, bool &gzip){
- time_t cur_time = time(NULL);
-
- if(params["compact"] != "1") {
+std::string worker::warning(std::string msg) {
+ std::string output = "15:warning message";
+ output += inttostr(msg.length());
+ output += ':';
+ output += msg;
+ return output;
+}
+
+std::string worker::announce(torrent &tor, user &u, std::map<std::string, std::string> &params, std::map<std::string, std::string> &headers, std::string &ip, bool &gzip) {
+ cur_time = time(NULL);
+
+ if (params["compact"] != "1") {
return error("Your client does not support compact announces");
}
-
+
int64_t left = strtolonglong(params["left"]);
int64_t uploaded = std::max((int64_t)0, strtolonglong(params["uploaded"]));
int64_t downloaded = std::max((int64_t)0, strtolonglong(params["downloaded"]));
int64_t corrupt = strtolonglong(params["corrupt"]);
-
+
+ int snatches = 0; // This is the value that gets sent to the database on a snatch
+ int active = 1; // This is the value that marks a peer as active/inactive in the database
bool inserted = false; // If we insert the peer as opposed to update
bool update_torrent = false; // Whether or not we should update the torrent in the DB
bool completed_torrent = false; // Whether or not the current announcement is a snatch
+ bool stopped_torrent = false; // Was the torrent just stopped?
bool expire_token = false; // Whether or not to expire a token after torrent completion
-
+ bool peer_changed = false; // Whether or not the peer is new or has changed since the last announcement
+
std::map<std::string, std::string>::const_iterator peer_id_iterator = params.find("peer_id");
- if(peer_id_iterator == params.end()) {
+ if (peer_id_iterator == params.end()) {
return error("No peer ID");
}
std::string peer_id = peer_id_iterator->second;
peer_id = hex_decode(peer_id);
-
- if(whitelist.size() > 0) {
+
+ if (whitelist.size() > 0) {
bool found = false; // Found client in whitelist?
- for(unsigned int i = 0; i < whitelist.size(); i++) {
- if(peer_id.find(whitelist[i]) == 0) {
+ for (unsigned int i = 0; i < whitelist.size(); i++) {
+ if (peer_id.find(whitelist[i]) == 0) {
found = true;
break;
}
}
- if(!found) {
+ if (!found) {
return error("Your client is not on the whitelist");
}
}
- if(params["event"] == "completed") {
+ if (params["event"] == "completed") {
+ // Don't update <snatches> here as we may decide to use other conditions later on
completed_torrent = true;
+ } else if (params["event"] == "stopped") {
+ stopped_torrent = true;
+ peer_changed = true;
+ update_torrent = true;
+ active = 0;
}
-
+
peer * p;
peer_list::iterator i;
// Insert/find the peer in the torrent list
- if(left > 0) {
+ if (left > 0) {
i = tor.leechers.find(peer_id);
- if(i == tor.leechers.end()) {
+ if (i == tor.leechers.end()) {
peer new_peer;
- std::pair<peer_list::iterator, bool> insert
+ std::pair<peer_list::iterator, bool> insert
= tor.leechers.insert(std::pair<std::string, peer>(peer_id, new_peer));
p = &(insert.first->second);
@@ -266,9 +295,9 @@ std::string worker::announce(torrent &tor, user &u, std::map<std::string, std::s
} else {
p = &i->second;
}
- } else if(completed_torrent) {
+ } else if (completed_torrent) {
i = tor.leechers.find(peer_id);
- if(i == tor.leechers.end()) {
+ if (i == tor.leechers.end()) {
peer new_peer;
std::pair<peer_list::iterator, bool> insert
= tor.seeders.insert(std::pair<std::string, peer>(peer_id, new_peer));
@@ -280,13 +309,13 @@ std::string worker::announce(torrent &tor, user &u, std::map<std::string, std::s
}
} else {
i = tor.seeders.find(peer_id);
- if(i == tor.seeders.end()) {
+ if (i == tor.seeders.end()) {
i = tor.leechers.find(peer_id);
- if(i == tor.leechers.end()) {
+ if (i == tor.leechers.end()) {
peer new_peer;
std::pair<peer_list::iterator, bool> insert
= tor.seeders.insert(std::pair<std::string, peer>(peer_id, new_peer));
-
+
p = &(insert.first->second);
inserted = true;
} else {
@@ -294,70 +323,66 @@ std::string worker::announce(torrent &tor, user &u, std::map<std::string, std::s
std::pair<peer_list::iterator, bool> insert
= tor.seeders.insert(std::pair<std::string, peer>(peer_id, *p));
tor.leechers.erase(peer_id);
- if(downloaded > 0) {
+ if (downloaded > 0) {
std::cout << "Found unreported snatch from user " << u.id << " on torrent " << tor.id << std::endl;
}
p = &(insert.first->second);
-// completed_torrent = true; // Not sure if we want to do this. Might cause massive spam for broken clients (e.g. µTorrent 3)
+ peer_changed = true;
+// completed_torrent = true; // Not sure if we want to do this. Will cause massive spam for weird clients (e.g. µTorrent 3 and Deluge)
}
} else {
p = &i->second;
}
-
+
tor.last_seeded = cur_time;
}
-
- // Update the peer
- p->left = left;
- p->visible = user_is_visible(&u);
+
int64_t upspeed = 0;
int64_t downspeed = 0;
- int64_t real_uploaded_change = 0;
- int64_t real_downloaded_change = 0;
-
- if(inserted || params["event"] == "started") {
+ if (inserted || params["event"] == "started") {
//New peer on this torrent
update_torrent = true;
p->userid = u.id;
- p->peer_id = peer_id;
p->first_announced = cur_time;
p->last_announced = 0;
p->uploaded = uploaded;
p->downloaded = downloaded;
p->corrupt = corrupt;
p->announces = 1;
- } else if(uploaded < p->uploaded || downloaded < p->downloaded) {
+ peer_changed = true;
+ } else if (uploaded < p->uploaded || downloaded < p->downloaded) {
p->announces++;
p->uploaded = uploaded;
p->downloaded = downloaded;
+ peer_changed = true;
} else {
int64_t uploaded_change = 0;
int64_t downloaded_change = 0;
int64_t corrupt_change = 0;
p->announces++;
-
- if(uploaded != p->uploaded) {
+
+ if (uploaded != p->uploaded) {
uploaded_change = uploaded - p->uploaded;
- real_uploaded_change = uploaded_change;
p->uploaded = uploaded;
}
- if(downloaded != p->downloaded) {
+ if (downloaded != p->downloaded) {
downloaded_change = downloaded - p->downloaded;
- real_downloaded_change = downloaded_change;
p->downloaded = downloaded;
}
- if(corrupt != p->corrupt) {
+ if (corrupt != p->corrupt) {
corrupt_change = corrupt - p->corrupt;
p->corrupt = corrupt;
tor.balance -= corrupt_change;
update_torrent = true;
}
- if(uploaded_change || downloaded_change) {
+ peer_changed = peer_changed || uploaded_change || downloaded_change || corrupt_change;
+
+ if (uploaded_change || downloaded_change) {
tor.balance += uploaded_change;
tor.balance -= downloaded_change;
update_torrent = true;
-
- if(cur_time > p->last_announced) {
+
+ if (cur_time > p->last_announced) {
upspeed = uploaded_change / (cur_time - p->last_announced);
downspeed = downloaded_change / (cur_time - p->last_announced);
}
@@ -365,8 +390,8 @@ std::string worker::announce(torrent &tor, user &u, std::map<std::string, std::s
if (tor.free_torrent == NEUTRAL) {
downloaded_change = 0;
uploaded_change = 0;
- } else if(tor.free_torrent == FREE || sit != tor.tokened_users.end()) {
- if(sit != tor.tokened_users.end()) {
+ } else if (tor.free_torrent == FREE || sit != tor.tokened_users.end()) {
+ if (sit != tor.tokened_users.end()) {
expire_token = true;
std::stringstream record;
record << '(' << u.id << ',' << tor.id << ',' << downloaded_change << ')';
@@ -375,9 +400,8 @@ std::string worker::announce(torrent &tor, user &u, std::map<std::string, std::s
}
downloaded_change = 0;
}
-
- if(uploaded_change || downloaded_change) {
-
+
+ if (uploaded_change || downloaded_change) {
std::stringstream record;
record << '(' << u.id << ',' << uploaded_change << ',' << downloaded_change << ')';
std::string record_str = record.str();
@@ -385,155 +409,184 @@ std::string worker::announce(torrent &tor, user &u, std::map<std::string, std::s
}
}
}
- p->last_announced = cur_time;
-
+ p->left = left;
+
std::map<std::string, std::string>::const_iterator param_ip = params.find("ip");
- if(param_ip != params.end()) {
+ if (param_ip != params.end()) {
ip = param_ip->second;
} else {
param_ip = params.find("ipv4");
- if(param_ip != params.end()) {
+ if (param_ip != params.end()) {
ip = param_ip->second;
}
}
-
+
unsigned int port = strtolong(params["port"]);
// Generate compact ip/port string
- if(inserted || port != p->port || ip != p->ip) {
+ if (inserted || port != p->port || ip != p->ip) {
p->port = port;
p->ip = ip;
p->ip_port = "";
char x = 0;
- for(size_t pos = 0, end = ip.length(); pos < end; pos++) {
- if(ip[pos] == '.') {
+ bool invalid_ip = false;
+ for (size_t pos = 0, end = ip.length(); pos < end; pos++) {
+ if (ip[pos] == '.') {
p->ip_port.push_back(x);
x = 0;
continue;
- } else if(!isdigit(ip[pos])) {
- return error("Unexpected character in IP address. Only IPv4 is currently supported");
+ } else if (!isdigit(ip[pos])) {
+ invalid_ip = true;
+ break;
}
x = x * 10 + ip[pos] - '0';
}
- p->ip_port.push_back(x);
- p->ip_port.push_back(port >> 8);
- p->ip_port.push_back(port & 0xFF);
- if(p->ip_port.length() != 6) {
- return error("Specified IP address is of a bad length");
+ if (!invalid_ip) {
+ p->ip_port.push_back(x);
+ p->ip_port.push_back(port >> 8);
+ p->ip_port.push_back(port & 0xFF);
}
+ if (p->ip_port.length() != 6) {
+ p->ip_port.clear();
+ invalid_ip = true;
+ }
+ p->invalid_ip = invalid_ip;
}
-
+
+ // Update the peer
+ p->last_announced = cur_time;
+ p->visible = peer_is_visible(&u, p);
+
+ // Add peer data to the database
+ std::stringstream record;
+ if (peer_changed) {
+ record << '(' << u.id << ',' << tor.id << ',' << active << ',' << uploaded << ',' << downloaded << ',' << upspeed << ',' << downspeed << ',' << left << ',' << corrupt << ',' << (cur_time - p->first_announced) << ',' << p->announces << ',';
+ std::string record_str = record.str();
+ std::string record_ip;
+ if (u.protect_ip) {
+ record_ip = "";
+ } else {
+ record_ip = ip;
+ }
+ db->record_peer(record_str, record_ip, peer_id, headers["user-agent"]);
+ } else {
+ record << '(' << tor.id << ',' << (cur_time - p->first_announced) << ',' << p->announces << ',';
+ std::string record_str = record.str();
+ db->record_peer(record_str, peer_id);
+ }
+
// Select peers!
unsigned int numwant;
std::map<std::string, std::string>::const_iterator param_numwant = params.find("numwant");
- if(param_numwant == params.end()) {
+ if (param_numwant == params.end()) {
numwant = 50;
} else {
numwant = std::min(50l, strtolong(param_numwant->second));
}
- int snatches = 0;
- int active = 1;
- if(params["event"] == "stopped") {
- update_torrent = true;
- active = 0;
+ if (stopped_torrent) {
numwant = 0;
-
- if(left > 0) {
- if(tor.leechers.erase(peer_id) == 0) {
+ if (left > 0) {
+ if (tor.leechers.erase(peer_id) == 0) {
std::cout << "Tried and failed to remove seeder from torrent " << tor.id << std::endl;
}
} else {
- if(tor.seeders.erase(peer_id) == 0) {
+ if (tor.seeders.erase(peer_id) == 0) {
std::cout << "Tried and failed to remove leecher from torrent " << tor.id << std::endl;
}
}
- } else if(completed_torrent) {
+ } else if (completed_torrent) {
snatches = 1;
update_torrent = true;
tor.completed++;
-
+
std::stringstream record;
- record << '(' << u.id << ',' << tor.id << ',' << cur_time << ", '" << ip << "')";
+ std::string record_ip;
+ if (u.protect_ip) {
+ record_ip = "";
+ } else {
+ record_ip = ip;
+ }
+ record << '(' << u.id << ',' << tor.id << ',' << cur_time << ", '" << record_ip << "')";
std::string record_str = record.str();
db->record_snatch(record_str);
-
+
// User is a seeder now!
- if(!inserted) {
+ if (!inserted) {
tor.seeders.insert(std::pair<std::string, peer>(peer_id, *p));
tor.leechers.erase(peer_id);
}
- if(expire_token) {
- (&s_comm)->expire_token(tor.id, u.id);
+ if (expire_token) {
+ s_comm->expire_token(tor.id, u.id);
tor.tokened_users.erase(u.id);
}
// do cache expire
- } else if(!u.can_leech && left > 0) {
+ } else if (!u.can_leech && left > 0) {
numwant = 0;
}
std::string peers;
- if(numwant > 0) {
+ if (numwant > 0) {
peers.reserve(numwant*6);
unsigned int found_peers = 0;
- if(left > 0) { // Show seeders to leechers first
- if(tor.seeders.size() > 0) {
+ if (left > 0) { // Show seeders to leechers first
+ if (tor.seeders.size() > 0) {
// We do this complicated stuff to cycle through the seeder list, so all seeders will get shown to leechers
-
+
// Find out where to begin in the seeder list
peer_list::const_iterator i;
- if(tor.last_selected_seeder == "") {
+ if (tor.last_selected_seeder == "") {
i = tor.seeders.begin();
} else {
i = tor.seeders.find(tor.last_selected_seeder);
- if(i == tor.seeders.end() || ++i == tor.seeders.end()) {
+ if (i == tor.seeders.end() || ++i == tor.seeders.end()) {
i = tor.seeders.begin();
}
}
-
+
// Find out where to end in the seeder list
peer_list::const_iterator end;
- if(i == tor.seeders.begin()) {
+ if (i == tor.seeders.begin()) {
end = tor.seeders.end();
} else {
end = i;
- if(--end == tor.seeders.begin()) {
+ if (--end == tor.seeders.begin()) {
end++;
i++;
}
}
-
+
// Add seeders
while(i != end && found_peers < numwant) {
- if(i == tor.seeders.end()) {
+ if (i == tor.seeders.end()) {
i = tor.seeders.begin();
}
// Don't show users themselves
- if (i->second.userid == p->userid) {
+ if (i->second.userid == p->userid || !i->second.visible) {
i++;
continue;
}
peers.append(i->second.ip_port);
found_peers++;
- tor.last_selected_seeder = i->second.peer_id;
+ tor.last_selected_seeder = i->first;
i++;
}
}
- if(found_peers < numwant && tor.leechers.size() > 1) {
- for(peer_list::const_iterator i = tor.leechers.begin(); i != tor.leechers.end() && found_peers < numwant; i++) {
+ if (found_peers < numwant && tor.leechers.size() > 1) {
+ for (peer_list::const_iterator i = tor.leechers.begin(); i != tor.leechers.end() && found_peers < numwant; i++) {
// Don't show users themselves or leech disabled users
- if(i->second.ip_port == p->ip_port || i->second.userid == p->userid || !i->second.visible) {
+ if (i->second.ip_port == p->ip_port || i->second.userid == p->userid || !i->second.visible) {
continue;
}
found_peers++;
peers.append(i->second.ip_port);
}
-
+
}
- } else if(tor.leechers.size() > 0) { // User is a seeder, and we have leechers!
- for(peer_list::const_iterator i = tor.leechers.begin(); i != tor.leechers.end() && found_peers < numwant; i++) {
+ } else if (tor.leechers.size() > 0) { // User is a seeder, and we have leechers!
+ for (peer_list::const_iterator i = tor.leechers.begin(); i != tor.leechers.end() && found_peers < numwant; i++) {
// Don't show users themselves or leech disabled users
- if(i->second.userid == p->userid || !i->second.visible) {
+ if (i->second.userid == p->userid || !i->second.visible) {
continue;
}
found_peers++;
@@ -542,7 +595,7 @@ std::string worker::announce(torrent &tor, user &u, std::map<std::string, std::s
}
}
- if(update_torrent || tor.last_flushed + 3600 < cur_time) {
+ if (update_torrent || tor.last_flushed + 3600 < cur_time) {
tor.last_flushed = cur_time;
std::stringstream record;
@@ -551,19 +604,7 @@ std::string worker::announce(torrent &tor, user &u, std::map<std::string, std::s
db->record_torrent(record_str);
}
- std::stringstream record;
- record << '(' << u.id << ',' << tor.id << ',' << active << ',' << uploaded << ',' << downloaded << ',' << upspeed << ',' << downspeed << ',' << left << ',' << corrupt << ',' << (cur_time - p->first_announced) << ',' << p->announces << ',';
- std::string record_str = record.str();
- db->record_peer(record_str, ip, peer_id, headers["user-agent"]);
-
- if (real_uploaded_change > 0 || real_downloaded_change > 0) {
- record.str("");
- record << '(' << u.id << ',' << downloaded << ',' << left << ',' << uploaded << ',' << upspeed << ',' << downspeed << ',' << (cur_time - p->first_announced);
- record_str = record.str();
- db->record_peer_hist(record_str, peer_id, tor.id);
- }
-
- if(!u.can_leech && left > 0) {
+ if (!u.can_leech && left > 0) {
return error("Access denied, leeching forbidden");
}
@@ -579,13 +620,16 @@ std::string worker::announce(torrent &tor, user &u, std::map<std::string, std::s
response += "e12:min intervali";
response += inttostr(conf->announce_interval);
response += "e5:peers";
- if(peers.length() == 0) {
+ if (peers.length() == 0) {
response += "0:";
} else {
response += inttostr(peers.length());
response += ":";
response += peers;
}
+ if (p->invalid_ip) {
+ response += warning("Illegal character found in IP address. IPv6 is not supported");
+ }
response += "e";
/* gzip compression actually makes announce returns larger from our
@@ -607,16 +651,16 @@ std::string worker::announce(torrent &tor, user &u, std::map<std::string, std::s
std::string worker::scrape(const std::list<std::string> &infohashes, std::map<std::string, std::string> &headers, bool &gzip) {
std::string output = "d5:filesd";
- for(std::list<std::string>::const_iterator i = infohashes.begin(); i != infohashes.end(); i++) {
+ for (std::list<std::string>::const_iterator i = infohashes.begin(); i != infohashes.end(); i++) {
std::string infohash = *i;
infohash = hex_decode(infohash);
-
+
torrent_list::iterator tor = torrents_list.find(infohash);
- if(tor == torrents_list.end()) {
+ if (tor == torrents_list.end()) {
continue;
}
torrent *t = &(tor->second);
-
+
output += inttostr(infohash.length());
output += ':';
output += infohash;
@@ -646,7 +690,7 @@ std::string worker::scrape(const std::list<std::string> &infohashes, std::map<st
//TODO: Restrict to local IPs
std::string worker::update(std::map<std::string, std::string> &params) {
- if(params["action"] == "change_passkey") {
+ if (params["action"] == "change_passkey") {
std::string oldpasskey = params["oldpasskey"];
std::string newpasskey = params["newpasskey"];
user_list::iterator i = users_list.find(oldpasskey);
@@ -657,14 +701,14 @@ std::string worker::update(std::map<std::string, std::string> &params) {
users_list.erase(oldpasskey);
std::cout << "Changed passkey from " << oldpasskey << " to " << newpasskey << " for user " << i->second.id << std::endl;
}
- } else if(params["action"] == "add_torrent") {
+ } else if (params["action"] == "add_torrent") {
torrent t;
t.id = strtolong(params["id"]);
std::string info_hash = params["info_hash"];
info_hash = hex_decode(info_hash);
- if(params["freetorrent"] == "0") {
+ if (params["freetorrent"] == "0") {
t.free_torrent = NORMAL;
- } else if(params["freetorrent"] == "1") {
+ } else if (params["freetorrent"] == "1") {
t.free_torrent = FREE;
} else {
t.free_torrent = NEUTRAL;
@@ -674,13 +718,13 @@ std::string worker::update(std::map<std::string, std::string> &params) {
t.last_selected_seeder = "";
torrents_list[info_hash] = t;
std::cout << "Added torrent " << t.id<< ". FL: " << t.free_torrent << " " << params["freetorrent"] << std::endl;
- } else if(params["action"] == "update_torrent") {
+ } else if (params["action"] == "update_torrent") {
std::string info_hash = params["info_hash"];
info_hash = hex_decode(info_hash);
freetype fl;
- if(params["freetorrent"] == "0") {
+ if (params["freetorrent"] == "0") {
fl = NORMAL;
- } else if(params["freetorrent"] == "1") {
+ } else if (params["freetorrent"] == "1") {
fl = FREE;
} else {
fl = NEUTRAL;
@@ -692,19 +736,19 @@ std::string worker::update(std::map<std::string, std::string> &params) {
} else {
std::cout << "Failed to find torrent " << info_hash << " to FL " << fl << std::endl;
}
- } else if(params["action"] == "update_torrents") {
+ } else if (params["action"] == "update_torrents") {
// Each decoded infohash is exactly 20 characters long.
std::string info_hashes = params["info_hashes"];
info_hashes = hex_decode(info_hashes);
freetype fl;
- if(params["freetorrent"] == "0") {
+ if (params["freetorrent"] == "0") {
fl = NORMAL;
- } else if(params["freetorrent"] == "1") {
+ } else if (params["freetorrent"] == "1") {
fl = FREE;
} else {
fl = NEUTRAL;
}
- for(unsigned int pos = 0; pos < info_hashes.length(); pos += 20) {
+ for (unsigned int pos = 0; pos < info_hashes.length(); pos += 20) {
std::string info_hash = info_hashes.substr(pos, 20);
auto torrent_it = torrents_list.find(info_hash);
if (torrent_it != torrents_list.end()) {
@@ -714,7 +758,7 @@ std::string worker::update(std::map<std::string, std::string> &params) {
std::cout << "Failed to find torrent " << info_hash << " to FL " << fl << std::endl;
}
}
- } else if(params["action"] == "add_token") {
+ } else if (params["action"] == "add_token") {
std::string info_hash = hex_decode(params["info_hash"]);
int user_id = atoi(params["userid"].c_str());
auto torrent_it = torrents_list.find(info_hash);
@@ -723,7 +767,7 @@ std::string worker::update(std::map<std::string, std::string> &params) {
} else {
std::cout << "Failed to find torrent to add a token for user " << user_id << std::endl;
}
- } else if(params["action"] == "remove_token") {
+ } else if (params["action"] == "remove_token") {
std::string info_hash = hex_decode(params["info_hash"]);
int user_id = atoi(params["userid"].c_str());
auto torrent_it = torrents_list.find(info_hash);
@@ -732,7 +776,7 @@ std::string worker::update(std::map<std::string, std::string> &params) {
} else {
std::cout << "Failed to find torrent " << info_hash << " to remove token for user " << user_id << std::endl;
}
- } else if(params["action"] == "delete_torrent") {
+ } else if (params["action"] == "delete_torrent") {
std::string info_hash = params["info_hash"];
info_hash = hex_decode(info_hash);
int reason = -1;
@@ -752,68 +796,78 @@ std::string worker::update(std::map<std::string, std::string> &params) {
} else {
std::cout << "Failed to find torrent " << info_hash << " to delete " << std::endl;
}
- } else if(params["action"] == "add_user") {
+ } else if (params["action"] == "add_user") {
std::string passkey = params["passkey"];
unsigned int id = strtolong(params["id"]);
user u;
u.id = id;
u.can_leech = 1;
+ if (params["visible"] == "0") {
+ u.protect_ip = 1;
+ } else {
+ u.protect_ip = 0;
+ }
users_list[passkey] = u;
std::cout << "Added user " << id << std::endl;
- } else if(params["action"] == "remove_user") {
+ } else if (params["action"] == "remove_user") {
std::string passkey = params["passkey"];
users_list.erase(passkey);
std::cout << "Removed user " << passkey << std::endl;
- } else if(params["action"] == "remove_users") {
+ } else if (params["action"] == "remove_users") {
// Each passkey is exactly 32 characters long.
std::string passkeys = params["passkeys"];
- for(unsigned int pos = 0; pos < passkeys.length(); pos += 32){
+ for (unsigned int pos = 0; pos < passkeys.length(); pos += 32) {
std::string passkey = passkeys.substr(pos, 32);
users_list.erase(passkey);
std::cout << "Removed user " << passkey << std::endl;
}
- } else if(params["action"] == "update_user") {
+ } else if (params["action"] == "update_user") {
std::string passkey = params["passkey"];
bool can_leech = true;
- if(params["can_leech"] == "0") {
+ bool protect_ip = false;
+ if (params["can_leech"] == "0") {
can_leech = false;
}
+ if (params["visible"] == "0") {
+ protect_ip = true;
+ }
user_list::iterator i = users_list.find(passkey);
if (i == users_list.end()) {
std::cout << "No user with passkey " << passkey << " found when attempting to change leeching status!" << std::endl;
} else {
+ users_list[passkey].protect_ip = protect_ip;
users_list[passkey].can_leech = can_leech;
std::cout << "Updated user " << passkey << std::endl;
}
- } else if(params["action"] == "add_whitelist") {
+ } else if (params["action"] == "add_whitelist") {
std::string peer_id = params["peer_id"];
whitelist.push_back(peer_id);
std::cout << "Whitelisted " << peer_id << std::endl;
- } else if(params["action"] == "remove_whitelist") {
+ } else if (params["action"] == "remove_whitelist") {
std::string peer_id = params["peer_id"];
- for(unsigned int i = 0; i < whitelist.size(); i++) {
- if(whitelist[i].compare(peer_id) == 0) {
+ for (unsigned int i = 0; i < whitelist.size(); i++) {
+ if (whitelist[i].compare(peer_id) == 0) {
whitelist.erase(whitelist.begin() + i);
break;
}
}
std::cout << "De-whitelisted " << peer_id << std::endl;
- } else if(params["action"] == "edit_whitelist") {
+ } else if (params["action"] == "edit_whitelist") {
std::string new_peer_id = params["new_peer_id"];
std::string old_peer_id = params["old_peer_id"];
- for(unsigned int i = 0; i < whitelist.size(); i++) {
- if(whitelist[i].compare(old_peer_id) == 0) {
+ for (unsigned int i = 0; i < whitelist.size(); i++) {
+ if (whitelist[i].compare(old_peer_id) == 0) {
whitelist.erase(whitelist.begin() + i);
break;
}
}
whitelist.push_back(new_peer_id);
std::cout << "Edited whitelist item from " << old_peer_id << " to " << new_peer_id << std::endl;
- } else if(params["action"] == "update_announce_interval") {
+ } else if (params["action"] == "update_announce_interval") {
unsigned int interval = strtolong(params["new_announce_interval"]);
conf->announce_interval = interval;
std::cout << "Edited announce interval to " << interval << std::endl;
- } else if(params["action"] == "info_torrent") {
+ } else if (params["action"] == "info_torrent") {
std::string info_hash_hex = params["info_hash"];
std::string info_hash = hex_decode(info_hash_hex);
std::cout << "Info for torrent '" << info_hash_hex << "'" << std::endl;
@@ -834,16 +888,15 @@ void worker::reap_peers() {
}
void worker::do_reap_peers() {
- db->logger_ptr->log("Began worker::do_reap_peers()");
std::cout << "Starting peer reaper" << std::endl;
- time_t cur_time = time(NULL);
+ cur_time = time(NULL);
unsigned int reaped = 0;
- std::unordered_map<std::string, torrent>::iterator i = torrents_list.begin();
- for(; i != torrents_list.end(); i++) {
- std::map<std::string, peer>::iterator p = i->second.leechers.begin();
- std::map<std::string, peer>::iterator del_p;
+ torrent_list::iterator i = torrents_list.begin();
+ for (; i != torrents_list.end(); i++) {
+ peer_list::iterator p = i->second.leechers.begin();
+ peer_list::iterator del_p;
while(p != i->second.leechers.end()) {
- if(p->second.last_announced + conf->peers_timeout < cur_time) {
+ if (p->second.last_announced + conf->peers_timeout < cur_time) {
del_p = p;
p++;
boost::mutex::scoped_lock lock(db->torrent_list_mutex);
@@ -855,7 +908,7 @@ void worker::do_reap_peers() {
}
p = i->second.seeders.begin();
while(p != i->second.seeders.end()) {
- if(p->second.last_announced + conf->peers_timeout < cur_time) {
+ if (p->second.last_announced + conf->peers_timeout < cur_time) {
del_p = p;
p++;
boost::mutex::scoped_lock lock(db->torrent_list_mutex);
@@ -867,7 +920,6 @@ void worker::do_reap_peers() {
}
}
std::cout << "Reaped " << reaped << " peers" << std::endl;
- db->logger_ptr->log("Completed worker::do_reap_peers()");
}
void worker::do_reap_del_reasons()
@@ -892,7 +944,7 @@ void worker::do_reap_del_reasons()
std::string worker::get_del_reason(int code)
{
- switch(code) {
+ switch (code) {
case DUPE:
return "Dupe";
break;
@@ -968,9 +1020,8 @@ std::string worker::get_del_reason(int code)
}
}
-bool worker::user_is_visible(user *u) {
- if(!u->can_leech) {
- return false;
- }
- return true;
+/* Peers should be invisible if they are a leecher without
+ download privs or their IP is invalid */
+bool worker::peer_is_visible(user *u, peer *p) {
+ return (p->left == 0 || u->can_leech) && !p->invalid_ip;
}