123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- import time
- import urllib.request
- import struct
- import socket
- import lib.bencode_open as bencode_open
- from lib.subtl.subtl import UdpTrackerClient
- import socks
- import sockshandler
- import gevent
- from Plugin import PluginManager
- from Config import config
- from Debug import Debug
- from util import helper
- # We can only import plugin host clases after the plugins are loaded
- @PluginManager.afterLoad
- def importHostClasses():
- global Peer, AnnounceError
- from Peer import Peer
- from Site.SiteAnnouncer import AnnounceError
- @PluginManager.registerTo("SiteAnnouncer")
- class SiteAnnouncerPlugin(object):
- def getSupportedTrackers(self):
- trackers = super(SiteAnnouncerPlugin, self).getSupportedTrackers()
- if config.disable_udp or config.trackers_proxy != "disable":
- trackers = [tracker for tracker in trackers if not tracker.startswith("udp://")]
- return trackers
- def getTrackerHandler(self, protocol):
- if protocol == "udp":
- handler = self.announceTrackerUdp
- elif protocol == "http":
- handler = self.announceTrackerHttp
- elif protocol == "https":
- handler = self.announceTrackerHttps
- else:
- handler = super(SiteAnnouncerPlugin, self).getTrackerHandler(protocol)
- return handler
- def announceTrackerUdp(self, tracker_address, mode="start", num_want=10):
- s = time.time()
- if config.disable_udp:
- raise AnnounceError("Udp disabled by config")
- if config.trackers_proxy != "disable":
- raise AnnounceError("Udp trackers not available with proxies")
- ip, port = tracker_address.split("/")[0].split(":")
- tracker = UdpTrackerClient(ip, int(port))
- if helper.getIpType(ip) in self.getOpenedServiceTypes():
- tracker.peer_port = self.fileserver_port
- else:
- tracker.peer_port = 0
- tracker.connect()
- if not tracker.poll_once():
- raise AnnounceError("Could not connect")
- tracker.announce(info_hash=self.site.address_sha1, num_want=num_want, left=431102370)
- back = tracker.poll_once()
- if not back:
- raise AnnounceError("No response after %.0fs" % (time.time() - s))
- elif type(back) is dict and "response" in back:
- peers = back["response"]["peers"]
- else:
- raise AnnounceError("Invalid response: %r" % back)
- return peers
- def httpRequest(self, url):
- headers = {
- 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11',
- 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
- 'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.3',
- 'Accept-Encoding': 'none',
- 'Accept-Language': 'en-US,en;q=0.8',
- 'Connection': 'keep-alive'
- }
- req = urllib.request.Request(url, headers=headers)
- if config.trackers_proxy == "tor":
- tor_manager = self.site.connection_server.tor_manager
- handler = sockshandler.SocksiPyHandler(socks.SOCKS5, tor_manager.proxy_ip, tor_manager.proxy_port)
- opener = urllib.request.build_opener(handler)
- return opener.open(req, timeout=50)
- elif config.trackers_proxy == "disable":
- return urllib.request.urlopen(req, timeout=25)
- else:
- proxy_ip, proxy_port = config.trackers_proxy.split(":")
- handler = sockshandler.SocksiPyHandler(socks.SOCKS5, proxy_ip, int(proxy_port))
- opener = urllib.request.build_opener(handler)
- return opener.open(req, timeout=50)
- def announceTrackerHttps(self, *args, **kwargs):
- kwargs["protocol"] = "https"
- return self.announceTrackerHttp(*args, **kwargs)
- def announceTrackerHttp(self, tracker_address, mode="start", num_want=10, protocol="http"):
- tracker_ip, tracker_port = tracker_address.rsplit(":", 1)
- if helper.getIpType(tracker_ip) in self.getOpenedServiceTypes():
- port = self.fileserver_port
- else:
- port = 1
- params = {
- 'info_hash': self.site.address_sha1,
- 'peer_id': self.peer_id, 'port': port,
- 'uploaded': 0, 'downloaded': 0, 'left': 431102370, 'compact': 1, 'numwant': num_want,
- 'event': 'started'
- }
- url = protocol + "://" + tracker_address + "?" + urllib.parse.urlencode(params)
- s = time.time()
- response = None
- # Load url
- if config.tor == "always" or config.trackers_proxy != "disable":
- timeout = 60
- else:
- timeout = 30
- with gevent.Timeout(timeout, False): # Make sure of timeout
- req = self.httpRequest(url)
- response = req.read()
- req.close()
- req = None
- if not response:
- raise AnnounceError("No response after %.0fs" % (time.time() - s))
- # Decode peers
- try:
- peer_data = bencode_open.loads(response)[b"peers"]
- response = None
- peer_count = int(len(peer_data) / 6)
- peers = []
- for peer_offset in range(peer_count):
- off = 6 * peer_offset
- peer = peer_data[off:off + 6]
- addr, port = struct.unpack('!LH', peer)
- peers.append({"addr": socket.inet_ntoa(struct.pack('!L', addr)), "port": port})
- except Exception as err:
- raise AnnounceError("Invalid response: %r (%s)" % (response, Debug.formatException(err)))
- return peers
|