diff options
Diffstat (limited to 'src/worker.cpp')
-rw-r--r-- | src/worker.cpp | 163 |
1 files changed, 130 insertions, 33 deletions
diff --git a/src/worker.cpp b/src/worker.cpp index c0e2e16..7ec604e 100644 --- a/src/worker.cpp +++ b/src/worker.cpp @@ -5,6 +5,8 @@ #include <sstream> #include <list> #include <vector> +#include <set> +#include <algorithm> #include <netinet/in.h> #include <arpa/inet.h> @@ -14,6 +16,7 @@ #include "db.h" #include "worker.h" #include "misc_functions.h" +#include "site_comm.h" #include <boost/thread/mutex.hpp> #include <boost/thread/thread.hpp> @@ -21,7 +24,20 @@ #include <boost/bind.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) : torrents_list(torrents), users_list(users), whitelist(_whitelist), conf(conf_obj), db(db_obj) { +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) { + if (status == OPEN) { + status = CLOSING; + std::cout << "closing tracker... press Ctrl-C again to terminate" << std::endl; + return false; + } else if (status == CLOSING) { + std::cout << "shutting down uncleanly" << std::endl; + return true; + } else { + return false; + } } std::string worker::work(std::string &input, std::string &ip) { unsigned int input_length = input.length(); @@ -69,6 +85,10 @@ std::string worker::work(std::string &input, std::string &ip) { if(action == INVALID) { return error("invalid action"); } + + if ((status != OPEN) && (action != UPDATE)) { + return error("The tracker is temporarily unavailable."); + } // Parse URL params std::list<std::string> infohashes; // For scrape only @@ -86,6 +106,7 @@ std::string worker::work(std::string &input, std::string &ip) { if(action == SCRAPE && key == "info_hash") { infohashes.push_back(value); } else { + params[key] = value; } key.clear(); @@ -118,6 +139,7 @@ std::string worker::work(std::string &input, std::string &ip) { 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; key.clear(); value.clear(); @@ -186,6 +208,7 @@ std::string worker::announce(torrent &tor, user &u, std::map<std::string, std::s 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 expire_token = false; // Whether or not to expire a token after torrent completion std::map<std::string, std::string>::const_iterator peer_id_iterator = params.find("peer_id"); if(peer_id_iterator == params.end()) { @@ -194,19 +217,20 @@ std::string worker::announce(torrent &tor, user &u, std::map<std::string, std::s std::string peer_id = peer_id_iterator->second; peer_id = hex_decode(peer_id); - bool found = false; // Found client in whitelist? - for(unsigned int i = 0; i < whitelist.size(); i++) { - if(peer_id.find(whitelist[i]) == 0) { - found = true; - break; + 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) { + found = true; + break; + } } - } - if(!found) { - return error("Your client is not on the whitelist"); + if(!found) { + return error("Your client is not on the whitelist"); + } } - peer * p; peer_list::iterator i; // Insert/find the peer in the torrent list @@ -246,29 +270,33 @@ std::string worker::announce(torrent &tor, user &u, std::map<std::string, std::s p->left = left; long long upspeed = 0; long long downspeed = 0; + long long real_uploaded_change = 0; + long long real_downloaded_change = 0; if(inserted || params["event"] == "started" || uploaded < p->uploaded || downloaded < p->downloaded) { //New peer on this torrent update_torrent = true; p->userid = u.id; p->peer_id = peer_id; - p->user_agent = headers["User-Agent"]; + p->user_agent = headers["user-agent"]; p->first_announced = cur_time; p->last_announced = 0; p->uploaded = uploaded; p->downloaded = downloaded; p->announces = 1; } else { - p->announces++; - long long uploaded_change = 0; long long downloaded_change = 0; + p->announces++; + if(uploaded != p->uploaded) { uploaded_change = uploaded - p->uploaded; + real_uploaded_change = uploaded_change; p->uploaded = uploaded; } if(downloaded != p->downloaded) { downloaded_change = downloaded - p->downloaded; + real_downloaded_change = downloaded_change; p->downloaded = downloaded; } if(uploaded_change || downloaded_change) { @@ -282,8 +310,18 @@ std::string worker::announce(torrent &tor, user &u, std::map<std::string, std::s upspeed = uploaded_change / (cur_time - p->last_announced); downspeed = downloaded_change / (cur_time - p->last_announced); } - - if(tor.free_torrent == true) { + std::set<int>::iterator sit = tor.tokened_users.find(u.id); + 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()) { + expire_token = true; + std::stringstream record; + record << '(' << u.id << ',' << tor.id << ',' << downloaded_change << ')'; + std::string record_str = record.str(); + db->record_token(record_str); + } downloaded_change = 0; } @@ -371,6 +409,11 @@ std::string worker::announce(torrent &tor, user &u, std::map<std::string, std::s // User is a seeder now! 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); + tor.tokened_users.erase(u.id); + } + // do cache expire } std::string peers; @@ -444,7 +487,14 @@ std::string worker::announce(torrent &tor, user &u, std::map<std::string, std::s std::stringstream record; record << '(' << u.id << ',' << tor.id << ',' << active << ',' << uploaded << ',' << downloaded << ',' << upspeed << ',' << downspeed << ',' << left << ',' << (cur_time - p->first_announced) << ',' << p->announces << ','; std::string record_str = record.str(); - db->record_peer(record_str, ip, peer_id, headers["User-Agent"]); + 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); + } std::string response = "d8:intervali"; response.reserve(350); @@ -499,34 +549,44 @@ std::string worker::scrape(const std::list<std::string> &infohashes) { //TODO: Restrict to local IPs std::string worker::update(std::map<std::string, std::string> ¶ms) { - std::cout << "Got update" << std::endl; if(params["action"] == "change_passkey") { std::string oldpasskey = params["oldpasskey"]; std::string newpasskey = params["newpasskey"]; - users_list[newpasskey] = users_list[oldpasskey]; - users_list.erase(oldpasskey); - std::cout << "changed passkey from " << oldpasskey << " to " << newpasskey << " for user " << users_list[newpasskey].id << std::endl; + user_list::iterator i = users_list.find(oldpasskey); + if (i == users_list.end()) { + std::cout << "No user with passkey " << oldpasskey << " exists when attempting to change passkey to " << newpasskey << std::endl; + } else { + users_list[newpasskey] = users_list[oldpasskey]; + users_list.erase(oldpasskey); + std::cout << "changed passkey from " << oldpasskey << " to " << newpasskey << " for user " << users_list[newpasskey].id << std::endl; + } } 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); - bool fl = false; - if(params["freetorrent"] == "1") { - fl = true; + if(params["freetorrent"] == "0") { + t.free_torrent = NORMAL; + } else if(params["freetorrent"] == "1") { + t.free_torrent = FREE; + } else { + t.free_torrent = NEUTRAL; } t.balance = 0; t.completed = 0; t.last_selected_seeder = ""; - t.free_torrent = fl; torrents_list[info_hash] = t; - std::cout << "Added torrent " << t.id << std::endl; + std::cout << "Added torrent " << t.id<< ". FL: " << t.free_torrent << " " << params["freetorrent"] << std::endl; } else if(params["action"] == "update_torrent") { std::string info_hash = params["info_hash"]; info_hash = hex_decode(info_hash); - bool fl = false; - if(params["freetorrent"] == "1") { - fl = true; + freetype fl; + if(params["freetorrent"] == "0") { + fl = NORMAL; + } else if(params["freetorrent"] == "1") { + fl = FREE; + } else { + fl = NEUTRAL; } if(torrents_list.find(info_hash) != torrents_list.end()) { torrents_list[info_hash].free_torrent = fl; @@ -538,9 +598,13 @@ std::string worker::update(std::map<std::string, std::string> ¶ms) { // Each decoded infohash is exactly 20 characters long. std::string info_hashes = params["info_hashes"]; info_hashes = hex_decode(info_hashes); - bool fl = false; - if(params["freetorrent"] == "1") { - fl = true; + freetype fl; + if(params["freetorrent"] == "0") { + fl = NORMAL; + } else if(params["freetorrent"] == "1") { + fl = FREE; + } else { + fl = NEUTRAL; } for(unsigned int pos = 0; pos < info_hashes.length(); pos += 20) { std::string info_hash = info_hashes.substr(pos, 20); @@ -551,6 +615,22 @@ std::string worker::update(std::map<std::string, std::string> ¶ms) { std::cout << "Failed to find torrent " << info_hash << " to FL " << fl << std::endl; } } + } else if(params["action"] == "add_token") { + std::string info_hash = hex_decode(params["info_hash"]); + int user_id = atoi(params["userid"].c_str()); + if(torrents_list.find(info_hash) != torrents_list.end()) { + torrents_list[info_hash].tokened_users.insert(user_id); + } else { + std::cout << "Failed to find torrent to add a token for user " << user_id << std::endl; + } + } else if(params["action"] == "remove_token") { + std::string info_hash = hex_decode(params["info_hash"]); + int user_id = atoi(params["userid"].c_str()); + if(torrents_list.find(info_hash) != torrents_list.end()) { + torrents_list[info_hash].tokened_users.erase(user_id); + } else { + std::cout << "Failed to find torrent " << info_hash << " to remove token for user " << user_id << std::endl; + } } else if(params["action"] == "delete_torrent") { std::string info_hash = params["info_hash"]; info_hash = hex_decode(info_hash); @@ -586,8 +666,13 @@ std::string worker::update(std::map<std::string, std::string> ¶ms) { if(params["can_leech"] == "0") { can_leech = false; } - users_list[passkey].can_leech = can_leech; - std::cout << "Updated user " << passkey << std::endl; + 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].can_leech = can_leech; + std::cout << "Updated user " << passkey << std::endl; + } } else if(params["action"] == "add_whitelist") { std::string peer_id = params["peer_id"]; whitelist.push_back(peer_id); @@ -616,6 +701,16 @@ std::string worker::update(std::map<std::string, std::string> ¶ms) { 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") { + 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; + if(torrents_list.find(info_hash) != torrents_list.end()) { + std::cout << "Torrent " << torrents_list[info_hash].id + << ", freetorrent = " << torrents_list[info_hash].free_torrent << std::endl; + } else { + std::cout << "Failed to find torrent " << info_hash_hex << std::endl; + } } return "success"; } @@ -626,6 +721,7 @@ void worker::reap_peers() { } void worker::do_reap_peers() { + db->logger_ptr->log("Began worker::do_reap_peers()"); time_t cur_time = time(NULL); unsigned int reaped = 0; std::unordered_map<std::string, torrent>::iterator i = torrents_list.begin(); @@ -657,4 +753,5 @@ void worker::do_reap_peers() { } } std::cout << "Reaped " << reaped << " peers" << std::endl; + db->logger_ptr->log("Completed worker::do_reap_peers()"); } |