From: Michael Tremer Date: Thu, 12 Oct 2017 13:50:08 +0000 (+0100) Subject: Drop tracker backend X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=69774f8b84ebe9f031ec50aef5da377fbe617e5d;p=ipfire.org.git Drop tracker backend Signed-off-by: Michael Tremer --- diff --git a/webapp/backend/base.py b/webapp/backend/base.py index 6cdb5a45..97449d8b 100644 --- a/webapp/backend/base.py +++ b/webapp/backend/base.py @@ -17,7 +17,6 @@ import planet import releases import settings import talk -import tracker import wishlist class Backend(object): @@ -47,7 +46,6 @@ class Backend(object): self.planet = planet.Planet(self) self.releases = releases.Releases(self) self.talk = talk.Talk(self) - self.tracker = tracker.Tracker(self) self.wishlist = wishlist.Wishlist(self) def read_config(self, configfile): diff --git a/webapp/backend/releases.py b/webapp/backend/releases.py index 6ea21f6f..42c8f75b 100644 --- a/webapp/backend/releases.py +++ b/webapp/backend/releases.py @@ -204,20 +204,6 @@ class File(Object): return s - @property - def seeders(self): - if not self.torrent_hash: - return - - return self.backend.tracker.complete(self.torrent_hash) - - @property - def peers(self): - if not self.torrent_hash: - return - - return self.backend.tracker.incomplete(self.torrent_hash) - class Release(Object): def __init__(self, backend, id, data=None): diff --git a/webapp/backend/tracker.py b/webapp/backend/tracker.py index 80f38c02..df72361a 100644 --- a/webapp/backend/tracker.py +++ b/webapp/backend/tracker.py @@ -2,201 +2,6 @@ from __future__ import division -import random - -from misc import Object - -def encode_hex(s): - return s.encode("hex") - -def decode_hex(s): - return s.decode("hex") - - -class Tracker(Object): - @property - def tracker_id(self): - return self.settings.get("tracker_id", "TheIPFireTorrentTracker") - - def _fuzzy_interval(self, interval, fuzz=120): - return interval - random.randint(0, fuzz) - - @property - def _interval(self): - return self.settings.get_int("tracker_interval", 3600) - - @property - def interval(self): - return self._fuzzy_interval(self._interval) - - @property - def min_interval(self): - return self.settings.get_int("tracker_min_interval", self._interval // 2) - - @property - def numwant(self): - return self.settings.get_int("tracker_numwant", 50) - - def get_peers(self, info_hash, limit=None, random=True, no_peer_id=False, ipfamily=None): - query = "SELECT * FROM tracker WHERE last_update >= NOW() - INTERVAL '%ss'" - args = [self._interval,] - - if info_hash: - query += " AND hash = %s" - args.append(info_hash) - - if random: - query += " ORDER BY RANDOM()" - - if limit: - query += " LIMIT %s" - args.append(limit) - - peers = [] - for row in self.db.query(query, *args): - peer6 = None - peer4 = None - - if row.address6 and row.port6: - peer6 = { - "ip" : row.address6, - "port" : row.port6, - } - - if row.address4 and row.port4: - peer4 = { - "ip" : row.address4, - "port" : row.port4, - } - - if not no_peer_id: - if peer6: - peer6["peer id"] = decode_hex(row.id) - - if peer4: - peer4["peer id"] = decode_hex(row.id) - - if peer6: - peers.append(peer6) - - if peer4: - peers.append(peer4) - - return peers - - def cleanup_peers(self): - """ - Remove all peers that have timed out. - """ - self.db.execute("DELETE FROM tracker \ - WHERE last_update < NOW() - INTERVAL '%s s'", int(self._interval * 1.2)) - - def update_peer(self, peer_id, info_hash, **kwargs): - # Translate the location IP address - address4 = kwargs.get("address4", None) - if address4 and address4.startswith("172.28.1."): - kwargs.update({ - "address4" : "178.63.73.246", - }) - - if self.peer_exists(peer_id, info_hash): - self.__update_peer(peer_id, info_hash, **kwargs) - else: - self.__insert_peer(peer_id, info_hash, **kwargs) - - def complete(self, info_hash): - ret = self.db.get("SELECT COUNT(*) AS c FROM tracker \ - WHERE hash = %s AND left_data = 0", info_hash) - - if ret: - return ret.c - - def incomplete(self, info_hash): - ret = self.db.get("SELECT COUNT(*) AS c FROM tracker \ - WHERE hash = %s AND left_data > 0", info_hash) - - if ret: - return ret.c - - def handle_event(self, event, peer_id, info_hash, **kwargs): - # stopped - if event == "stopped": - self.remove_peer(peer_id, info_hash) - - def peer_exists(self, peer_id, info_hash): - ret = self.db.get("SELECT COUNT(*) AS c FROM tracker \ - WHERE id = %s AND hash = %s", peer_id, info_hash) - - if ret and ret.c > 0: - return True - - return False - - def __insert_peer(self, peer_id, info_hash, address6=None, port6=None, address4=None, port4=None, left_data=0, **kwargs): - self.db.execute("INSERT INTO tracker(id, hash, address6, port6, address4, port4, left_data) \ - VALUES(%s, %s, %s, %s, %s, %s, %s)", peer_id, info_hash, address6, port6, address4, port4, left_data) - - def __update_peer(self, peer_id, info_hash, address6=None, port6=None, - address4=None, port4=None, downloaded=None, uploaded=None, left_data=None): - query = "UPDATE tracker SET last_update = NOW()" - args = [] - - if address6: - query += ", address6 = %s" - args.append(address6) - - if port6: - query += ", port6 = %s" - args.append(port6) - - if address4: - query += ", address4 = %s" - args.append(address4) - - if port4: - query += ", port4 = %s" - args.append(port4) - - if downloaded: - query += ", downloaded = %s" - args.append(downloaded) - - if uploaded: - query += ", uploaded = %s" - args.append(uploaded) - - if left_data: - query += ", left_data = %s" - args.append(left_data) - - query += " WHERE id = %s AND hash = %s" - args += [peer_id, info_hash] - - self.db.execute(query, *args) - - def remove_peer(self, peer_id, info_hash): - self.db.execute("DELETE FROM tracker \ - WHERE id = %s AND hash = %s", peer_id, info_hash) - - def scrape(self, info_hashes): - ret = { - "files" : {}, - "flags" : { - "min_request_interval" : self.interval, - } - } - - if info_hashes: - for info_hash in info_hashes: - ret["files"][info_hash] = { - "complete" : self.complete(info_hash), - "incomplete" : self.incomplete(info_hash), - "downloaded" : 0, - } - - return ret - - ##### This is borrowed from the bittorrent client libary ##### def decode_int(x, f): diff --git a/webapp/handlers_tracker.py b/webapp/handlers_tracker.py deleted file mode 100644 index ba2f6618..00000000 --- a/webapp/handlers_tracker.py +++ /dev/null @@ -1,197 +0,0 @@ -#!/usr/bin/python - -import re -import tornado.web - -from backend.tracker import bencode, bdecode, encode_hex, decode_hex -from handlers_base import * - - -class TrackerIndexHandler(BaseHandler): - def get(self): - releases = self.releases.get_all() - - limit = 5 - releases = releases[:limit] - - self.render("tracker-torrents.html", releases=releases) - - -class TrackerDetailHandler(BaseHandler): - def get(self, torrent_hash): - file = self.releases.get_file_for_torrent_hash(torrent_hash) - - if not file: - raise tornado.web.HTTPError(404, "Could not find torrent file for hash: %s" % torrent_hash) - - peers = self.tracker.get_peers(torrent_hash) - - self.render("tracker-torrent-detail.html", release=file.release, - file=file, peers=peers) - - -class TrackerDownloadHandler(BaseHandler): - def get(self, torrent_hash): - file = self.releases.get_file_for_torrent_hash(torrent_hash) - - if not file: - raise tornado.web.HTTPError(404, "Could not find torrent file for hash: %s" % torrent_hash) - - # Redirect the user to the download redirector. - self.redirect("http://downloads.ipfire.org/%s.torrent" % file.filename) - - -class TrackerBaseHandler(BaseHandler): - def get_hexencoded_argument(self, name, all=False): - try: - arguments = self.request.arguments[name] - except KeyError: - return None - - arguments_new = [] - for argument in arguments: - arguments_new.append(encode_hex(argument)) - - arguments = arguments_new - - if all: - return arguments - - return arguments[0] - - def send_tracker_error(self, error_message): - msg = bencode({"failure reason" : error_message }) - self.finish(msg) - - -class TrackerAnnounceHandler(TrackerBaseHandler): - def prepare(self): - self.set_header("Content-Type", "text/plain") - - def get_ipv6_address(self, default_port): - # Get the external IP address of the client. - addr = self.get_remote_ip() - - if ":" in addr: - return addr, default_port - - # IPv6 - ipv6 = self.get_argument("ipv6", None) - if ipv6: - port = default_port - - m = re.match("^\[(.*)\]\:(\d)$", ipv6) - if m: - ipv6, port = (m.group(1), m.group(2)) - - return ipv6, port - - return None, None - - def get_ipv4_address(self, default_port): - # Get the external IP address of the client. - addr = self.get_remote_ip() - - if addr.startswith("172.28.1."): - addr = "178.63.73.246" - - if not ":" in addr: - return addr, default_port - - # IPv4 - ipv4 = self.get_argument("ipv4", None) - if ipv4: - return ipv4, default_port - - ip = self.get_argument("ip", None) - if ip: - return ip, default_port - - return None, None - - def get_port(self): - # Get the port and check it for sanity - port = self.get_argument("port", None) - - try: - port = int(port) - - if port < 0 or port > 65535: - raise ValueError - except (TypeError, ValueError): - port = None - - return port - - def get(self): - # Get the info hash - info_hash = self.get_hexencoded_argument("info_hash") - if not info_hash: - self.send_tracker_error("Your client forgot to send your torrent's info_hash") - return - - # Get the peer id - peer_id = self.get_hexencoded_argument("peer_id") - - # Get the port and check it for sanity - port = self.get_port() - if not port: - self.send_tracker_error("Invalid port number or port number missing") - return - - addr_ipv6, port_ipv6 = self.get_ipv6_address(port) - addr_ipv4, port_ipv4 = self.get_ipv4_address(port) - - # Handle events - event = self.get_argument("event", None) - if event: - if not event in ("started", "stopped", "completed"): - self.send_tracker_error("Got unknown event") - return - - self.tracker.handle_event(event, peer_id, info_hash) - - if event == "stopped": - return - - peer_info = { - "address6" : addr_ipv6, - "port6" : port_ipv6, - "address4" : addr_ipv4, - "port4" : port_ipv4, - "downloaded" : self.get_argument("downloaded", 0), - "uploaded" : self.get_argument("uploaded", 0), - "left_data" : self.get_argument("left", 0), - } - - self.tracker.update_peer(peer_id, info_hash, **peer_info) - - no_peer_id = self.get_argument("no_peer_id", False) - numwant = self.get_argument("numwant", self.tracker.numwant) - - peers = self.tracker.get_peers(info_hash, limit=numwant, no_peer_id=no_peer_id) - - response = bencode({ - "tracker id" : self.tracker.tracker_id, - "interval" : self.tracker.interval, - "min interval" : self.tracker.min_interval, - "peers" : peers, - "complete" : self.tracker.complete(info_hash), - "incomplete" : self.tracker.incomplete(info_hash), - }) - self.finish(response) - - def on_finish(self): - """ - Cleanup after every request. - """ - self.tracker.cleanup_peers() - - -class TrackerScrapeHandler(TrackerBaseHandler): - def get(self): - info_hashes = self.get_hexencoded_argument("info_hash", all=True) - - response = self.tracker.scrape(info_hashes) - - self.finish(bencode(response))