]>
Commit | Line | Data |
---|---|---|
940227cb MT |
1 | #!/usr/bin/python |
2 | ||
3 | import tornado.web | |
4 | ||
5 | from backend.tracker import bencode, bdecode, decode_hex | |
6 | from handlers_base import * | |
7 | ||
8 | ||
9 | class TrackerIndexHandler(BaseHandler): | |
10 | def get(self): | |
11 | hashes = self.tracker.hashes | |
12 | ||
13 | torrents = [] | |
14 | for release in self.releases.list(): | |
15 | if not release.torrent_hash: | |
16 | continue | |
17 | ||
18 | if release.torrent_hash in hashes: | |
19 | torrents.append(tornado.database.Row({ | |
20 | "name" : release.name, | |
21 | "hash" : release.torrent_hash.lower(), | |
22 | "peers" : self.tracker.incomplete(release.torrent_hash), | |
23 | "seeds" : self.tracker.complete(release.torrent_hash), | |
24 | })) | |
25 | ||
26 | self.render("tracker-torrents.html", torrents=torrents) | |
27 | ||
28 | ||
29 | class TrackerDetailHandler(BaseHandler): | |
30 | def get(self, hash): | |
31 | release = None | |
32 | for r in self.releases.list(): | |
33 | if not r.torrent_hash: | |
34 | continue | |
35 | ||
36 | if r.torrent_hash.lower() == hash.lower(): | |
37 | release = r | |
38 | break | |
39 | ||
40 | if not release: | |
41 | raise tornado.web.HTTPError(404) | |
42 | ||
43 | torrent = tornado.database.Row({ | |
44 | "peers" : self.tracker.get_peers(hash), | |
45 | "seeds" : self.tracker.get_seeds(hash), | |
46 | }) | |
47 | ||
48 | self.render("tracker-torrent-detail.html", release=release, torrent=torrent) | |
49 | ||
50 | ||
51 | #class TrackerTorrentsHandler(BaseHandler): | |
52 | # @property | |
53 | # def tracker(self): | |
54 | # return self.tracker | |
55 | # | |
56 | # def get(self): | |
57 | # releases = [] | |
58 | # | |
59 | # for release in self.releases.get_all(): | |
60 | # if not release.torrent_hash: | |
61 | # continue | |
62 | # | |
63 | # release.torrent_hash = release.torrent_hash.lower() | |
64 | # | |
65 | # release.torrent_peers = self.tracker.incomplete(release.torrent_hash) | |
66 | # release.torrent_seeds = self.tracker.complete(release.torrent_hash) | |
67 | # | |
68 | # releases.append(release) | |
69 | # | |
70 | # self.render("tracker-torrents.html", releases=releases) | |
71 | ||
72 | ||
73 | class TrackerBaseHandler(tornado.web.RequestHandler): | |
74 | @property | |
75 | def tracker(self): | |
76 | return backend.Tracker() | |
77 | ||
78 | def get_hexencoded_argument(self, name, all=False): | |
79 | try: | |
80 | arguments = self.request.arguments[name] | |
81 | except KeyError: | |
82 | return None | |
83 | ||
84 | arguments_new = [] | |
85 | for argument in arguments: | |
86 | arguments_new.append(decode_hex(argument)) | |
87 | ||
88 | arguments = arguments_new | |
89 | ||
90 | if all: | |
91 | return arguments | |
92 | ||
93 | return arguments[0] | |
94 | ||
95 | def send_tracker_error(self, error_message): | |
96 | self.write(bencode({"failure reason" : error_message })) | |
97 | self.finish() | |
98 | ||
99 | ||
100 | class TrackerAnnounceHandler(TrackerBaseHandler): | |
101 | def get(self): | |
102 | self.set_header("Content-Type", "text/plain") | |
103 | ||
104 | info_hash = self.get_hexencoded_argument("info_hash") | |
105 | if not info_hash: | |
106 | self.send_tracker_error("Your client forgot to send your torrent's info_hash.") | |
107 | return | |
108 | ||
109 | peer = { | |
110 | "id" : self.get_hexencoded_argument("peer_id"), | |
111 | "ip" : self.request.remote_ip, | |
112 | "port" : self.get_argument("port", None), | |
113 | "downloaded" : self.get_argument("downloaded", 0), | |
114 | "uploaded" : self.get_argument("uploaded", 0), | |
115 | "left" : self.get_argument("left", 0), | |
116 | } | |
117 | ||
118 | event = self.get_argument("event", "") | |
119 | if not event in ("started", "stopped", "completed", ""): | |
120 | self.send_tracker_error("Got unknown event") | |
121 | return | |
122 | ||
123 | if peer["port"]: | |
124 | peer["port"] = int(peer["port"]) | |
125 | ||
126 | if peer["port"] < 0 or peer["port"] > 65535: | |
127 | self.send_tracker_error("Port number is not in valid range") | |
128 | return | |
129 | ||
130 | eventhandlers = { | |
131 | "started" : self.tracker.event_started, | |
132 | "stopped" : self.tracker.event_stopped, | |
133 | "completed" : self.tracker.event_completed, | |
134 | } | |
135 | ||
136 | if event: | |
137 | eventhandlers[event](info_hash, peer["id"]) | |
138 | ||
139 | self.tracker.update(hash=info_hash, **peer) | |
140 | ||
141 | no_peer_id = self.get_argument("no_peer_id", False) | |
142 | numwant = self.get_argument("numwant", self.tracker.numwant) | |
143 | ||
144 | self.write(bencode({ | |
145 | "tracker id" : self.tracker.id, | |
146 | "interval" : self.tracker.interval, | |
147 | "min interval" : self.tracker.min_interval, | |
148 | "peers" : self.tracker.get_peers(info_hash, limit=numwant, | |
149 | random=True, no_peer_id=no_peer_id), | |
150 | "complete" : self.tracker.complete(info_hash), | |
151 | "incomplete" : self.tracker.incomplete(info_hash), | |
152 | })) | |
153 | self.finish() | |
154 | ||
155 | ||
156 | class TrackerScrapeHandler(TrackerBaseHandler): | |
157 | def get(self): | |
158 | info_hashes = self.get_hexencoded_argument("info_hash", all=True) | |
159 | ||
160 | self.write(bencode(self.tracker.scrape(hashes=info_hashes))) | |
161 | self.finish() |