Убрал ненужную прослойку при передаче параметров

sandbox1
inpos 2016-03-10 19:55:25 +03:00
parent f9840c39c0
commit 9740ebf6f3
3 changed files with 122 additions and 182 deletions

View File

@ -99,8 +99,8 @@ class Engine:
enable_dht=True, enable_lsd=True, enable_natpmp=True, enable_upnp=True, enable_scrape=False, enable_dht=True, enable_lsd=True, enable_natpmp=True, enable_upnp=True, enable_scrape=False,
log_stats=False, encryption=Encryption.ENABLED, keep_complete=False, keep_incomplete=False, log_stats=False, encryption=Encryption.ENABLED, keep_complete=False, keep_incomplete=False,
keep_files=False, log_files_progress=False, log_overall_progress=False, log_pieces_progress=False, keep_files=False, log_files_progress=False, log_overall_progress=False, log_pieces_progress=False,
listen_port=6881, use_random_port=False, max_idle_timeout=None, no_sparse=False, resume_file=None, listen_port=6881, use_random_port=False, max_idle_timeout=None, no_sparse=False, resume_file='',
user_agent=None, startup_timeout=5, state_file=None, enable_utp=True, enable_tcp=True, user_agent=None, startup_timeout=5, state_file='', enable_utp=True, enable_tcp=True,
debug_alerts=False, logger=None, torrent_connect_boost=50, connection_speed=50, debug_alerts=False, logger=None, torrent_connect_boost=50, connection_speed=50,
peer_connect_timeout=15, request_timeout=20, min_reconnect_time=60, max_failcount=3, peer_connect_timeout=15, request_timeout=20, min_reconnect_time=60, max_failcount=3,
dht_routers=None, trackers=None): dht_routers=None, trackers=None):
@ -239,61 +239,46 @@ class Engine:
self.bind_port = port self.bind_port = port
kwargs = { kwargs = {
'--bind': "%s:%s" % (self.bind_host, self.bind_port), 'torrentConnectBoost': self.torrent_connect_boost,
'--uri': self.uri, 'trackers': ",".join(self.trackers),
'--file-index': start_index, 'resumeFile': self.resume_file,
'--dl-path': download_path, 'minReconnectTime': self.min_reconnect_time,
'--connections-limit': self.connections_limit, 'enableUPNP': self.enable_upnp,
'--dl-rate': self.download_kbps, 'showAllStats': self.log_stats,
'--ul-rate': self.upload_kbps, 'debugAlerts': self.debug_alerts,
'--enable-dht': self.enable_dht, 'keepComplete': self.keep_complete,
'--enable-lsd': self.enable_lsd, 'dhtRouters': ",".join(self.dht_routers),
'--enable-natpmp': self.enable_natpmp, 'userAgent': self.user_agent,
'--enable-upnp': self.enable_upnp, 'enableLSD': self.enable_lsd,
'--enable-scrape': self.enable_scrape, 'uri': self.uri,
'--encryption': self.encryption, 'randomPort': self.use_random_port,
'--show-stats': self.log_stats, 'noSparseFile': self.no_sparse,
'--files-progress': self.log_files_progress, 'maxUploadRate': self.upload_kbps,
'--overall-progress': self.log_overall_progress, 'downloadPath': download_path,
'--pieces-progress': self.log_pieces_progress, 'showOverallProgress': self.log_overall_progress,
'--listen-port': self.listen_port, 'enableDHT': self.enable_dht,
'--random-port': self.use_random_port, 'showFilesProgress': self.log_files_progress,
'--keep-complete': self.keep_complete, 'requestTimeout': self.request_timeout,
'--keep-incomplete': self.keep_incomplete, 'bindAddress': "%s:%s" % (self.bind_host, self.bind_port),
'--keep-files': self.keep_files, 'maxDownloadRate': self.download_kbps,
'--max-idle': self.max_idle_timeout, 'connectionSpeed': self.connection_speed,
'--no-sparse': self.no_sparse, 'keepIncomplete': self.keep_incomplete,
'--resume-file': self.resume_file, 'enableTCP': self.enable_tcp,
'--user-agent': self.user_agent, 'listenPort': self.listen_port,
'--state-file': self.state_file, 'keepFiles': self.keep_files,
'--enable-utp': self.enable_utp, 'stateFile': self.state_file,
'--enable-tcp': self.enable_tcp, 'peerConnectTimeout': self.peer_connect_timeout,
'--debug-alerts': self.debug_alerts, 'maxFailCount': self.max_failcount,
'--torrent-connect-boost': self.torrent_connect_boost, 'showPiecesProgress': self.log_pieces_progress,
'--connection-speed': self.connection_speed, 'idleTimeout': self.max_idle_timeout,
'--peer-connect-timeout': self.peer_connect_timeout, 'fileIndex': start_index,
'--request-timeout': self.request_timeout, 'connectionsLimit': self.connections_limit,
'--min-reconnect-time': self.min_reconnect_time, 'enableScrape': self.enable_scrape,
'--max-failcount': self.max_failcount, 'enableUTP': self.enable_utp,
'--dht-routers': ",".join(self.dht_routers), 'encryption': self.encryption,
'--trackers': ",".join(self.trackers), 'enableNATPMP': self.enable_natpmp
}
args = [] }
for k, v in kwargs.iteritems():
if v is not None:
if isinstance(v, bool):
if v:
args.append(k)
else:
args.append("%s=false" % k)
else:
args.append(k)
if isinstance(v, str) or isinstance(v, unicode):
v = ensure_fs_encoding(v)
else:
v = str(v)
args.append(v)
self._log("Invoking pyrrent2http") self._log("Invoking pyrrent2http")
class Logging(object): class Logging(object):
@ -306,22 +291,19 @@ class Engine:
if LOGGING: if LOGGING:
self._log('ERROR: %s' % (message,)) self._log('ERROR: %s' % (message,))
pyrrent2http.logging = Logging(self._log) pyrrent2http.logging = Logging(self._log)
# startupinfo = None
# if self.platform.system == "windows":
# startupinfo = subprocess.STARTUPINFO()
# startupinfo.dwFlags |= 1
# startupinfo.wShowWindow = 0
#
# self.logpipe = logpipe.LogPipe(self._log)
# try:
# self.process = subprocess.Popen(args, stderr=self.logpipe, stdout=self.logpipe, startupinfo=startupinfo)
# except OSError, e:
# raise Error("Can't start pyrrent2http: %r" % e, Error.POPEN_ERROR)
self.pyrrent2http = pyrrent2http.Pyrrent2http() self.pyrrent2http = pyrrent2http.Pyrrent2http()
self.pyrrent2http.parseFlags(args) self._log('init config')
self.pyrrent2http.startSession() try:
self.pyrrent2http.initConfig(**kwargs)
except Exception as e:
self._log('%s' % (e.args,))
self._log('Starting session')
try:
self.pyrrent2http.startSession()
except Exception as e:
self._log('%s' % (e.args,))
self._log('starting services')
self.pyrrent2http.startServices() self.pyrrent2http.startServices()
self.pyrrent2http.addTorrent() self.pyrrent2http.addTorrent()
self.pyrrent2http.startHTTP() self.pyrrent2http.startHTTP()
@ -440,34 +422,6 @@ class Engine:
def is_alive(self): def is_alive(self):
return self.pyrrent2http_loop.is_alive() return self.pyrrent2http_loop.is_alive()
__to_del = '''@staticmethod
def _decode(response):
try:
return json.loads(response)
except (KeyError, ValueError), e:
raise Error("Can't decode response from pyrrent2http: %r" % e, Error.REQUEST_ERROR)
'''
__to_del = '''def _request(self, cmd, timeout=None):
if not self.started:
raise Error("pyrrent2http is not started", Error.REQUEST_ERROR)
try:
url = "http://%s:%s/%s" % (self.bind_host, self.bind_port, cmd)
kwargs = {}
if timeout is not None:
kwargs['timeout'] = timeout
return urllib2.urlopen(url, **kwargs).read()
except (urllib2.URLError, httplib.HTTPException) as e:
if isinstance(e, urllib2.URLError) and isinstance(e.reason, socket.timeout):
raise Error("Timeout occurred while sending command '%s' to pyrrent2http" % cmd, Error.TIMEOUT)
elif not self.is_alive() and self.started:
raise Error("pyrrent2http has crashed.", Error.CRASHED)
else:
raise Error("Can't send command '%s' to pyrrent2http: %r" % (cmd, e), Error.REQUEST_ERROR)
except socket.error as e:
reason = e[1] if isinstance(e, tuple) else e
raise Error("Can't read from pyrrent2http: %s" % reason, Error.REQUEST_ERROR)
'''
def wait_on_close(self, wait_timeout=10): def wait_on_close(self, wait_timeout=10):
""" """
By default, close() method sends shutdown command to pyrrent2http, stops logging and returns immediately, not By default, close() method sends shutdown command to pyrrent2http, stops logging and returns immediately, not
@ -483,16 +437,12 @@ class Engine:
Shuts down pyrrent2http and stops logging. If wait_on_close() was called earlier, it will wait until Shuts down pyrrent2http and stops logging. If wait_on_close() was called earlier, it will wait until
pyrrent2http successfully exits. pyrrent2http successfully exits.
""" """
# if self.logpipe and self.wait_on_close_timeout is None:
# self.logpipe.close()
if self.is_alive(): if self.is_alive():
self._log("Shutting down pyrrent2http...") self._log("Shutting down pyrrent2http...")
# self._request('shutdown')
self.pyrrent2http.shutdown() self.pyrrent2http.shutdown()
finished = False finished = False
if self.wait_on_close_timeout is not None: if self.wait_on_close_timeout is not None:
start = time.time() start = time.time()
# os.close(self.logpipe.write_fd)
while (time.time() - start) < self.wait_on_close_timeout: while (time.time() - start) < self.wait_on_close_timeout:
time.sleep(0.5) time.sleep(0.5)
if not self.is_alive(): if not self.is_alive():
@ -500,11 +450,9 @@ class Engine:
break break
if not finished: if not finished:
self._log("PANIC: Timeout occurred while shutting down pyrrent2http thread") self._log("PANIC: Timeout occurred while shutting down pyrrent2http thread")
#self.process.kill()
else: else:
self._log("pyrrent2http successfully shut down.") self._log("pyrrent2http successfully shut down.")
self.wait_on_close_timeout = None self.wait_on_close_timeout = None
# self.process.wait()
self.started = False self.started = False
self.logpipe = None self.logpipe = None
self.process = None self.process = None

View File

@ -1,6 +1,5 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import argparse
import sys, os import sys, os
import json import json
import chardet import chardet
@ -28,7 +27,7 @@ import BaseHTTPServer
import SocketServer import SocketServer
import threading import threading
import io import io
from util import localize_path from util import localize_path, Struct
@ -423,20 +422,6 @@ class TorrentFS(object):
############################################################# #############################################################
class AttributeDict(dict):
def __getattr__(self, attr):
return self[attr]
def __setattr__(self, attr, value):
self[attr] = value
class BoolArg(argparse.Action):
def __call__(self, parser, namespace, values, option_string=None):
#print(repr(values))
if values is None: v = True
elif values.lower() == 'true': v = True
elif values.lower() == 'false': v = False
setattr(namespace, self.dest, v)
class ThreadingHTTPServer(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer): class ThreadingHTTPServer(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer):
def handle_error(self, *args, **kwargs): def handle_error(self, *args, **kwargs):
'''Обходим злосчастный "Broken Pipe" и прочие трейсы''' '''Обходим злосчастный "Broken Pipe" и прочие трейсы'''
@ -591,68 +576,67 @@ class Pyrrent2http(object):
self.forceShutdown = False self.forceShutdown = False
self.session = None self.session = None
self.magnet = False self.magnet = False
def parseFlags(self, params = None): def initConfig(self, uri = '', bindAddress = 'localhost:5001', downloadPath = '.',
parser = argparse.ArgumentParser(add_help=True, version=VERSION) idleTimeout = -1, fileIndex = -1, keepComplete = False,
parser.add_argument('--uri', type=str, default='', help='Magnet URI or .torrent file URL', dest='uri') keepIncomplete = False, keepFiles = False, showAllStats = False,
parser.add_argument('--bind', type=str, default='localhost:5001', help='Bind address of torrent2http', dest='bindAddress') showOverallProgress = False, showFilesProgress = False,
parser.add_argument('--dl-path', type=str, default='.', help='Download path', dest='downloadPath') showPiecesProgress = False, debugAlerts = False,
parser.add_argument('--max-idle', type=int, default=-1, help='Automatically shutdown if no connection are active after a timeout', dest='idleTimeout') exitOnFinish = False, resumeFile = '', stateFile = '',
parser.add_argument('--file-index', type=int, default=-1, help='Start downloading file with specified index immediately (or start in paused state otherwise)', dest='fileIndex') userAgent = USER_AGENT, dhtRouters = '', trackers = '',
parser.add_argument('--keep-complete', nargs='?', action=BoolArg, default=False, help='Keep complete files after exiting', dest='keepComplete', choices=('true', 'false')) listenPort = 6881, torrentConnectBoost = 50, connectionSpeed = 50,
parser.add_argument('--keep-incomplete', nargs='?', action=BoolArg, default=False, help='Keep incomplete files after exiting', dest='keepIncomplete', choices=('true', 'false')) peerConnectTimeout = 15, requestTimeout = 20, maxDownloadRate = -1,
parser.add_argument('--keep-files', nargs='?', action=BoolArg, default=False, help='Keep all files after exiting (incl. -keep-complete and -keep-incomplete)', dest='keepFiles', choices=('true', 'false')) maxUploadRate = -1, connectionsLimit = 200, encryption = 1,
parser.add_argument('--show-stats', nargs='?', action=BoolArg, default=False, help='Show all stats (incl. -overall-progress -files-progress -pieces-progress)', dest='showAllStats', choices=('true', 'false')) minReconnectTime = 60, maxFailCount = 3, noSparseFile = False,
parser.add_argument('--overall-progress', nargs='?', action=BoolArg, default=False, help='Show overall progress', dest='showOverallProgress', choices=('true', 'false')) randomPort = False, enableScrape = False, enableDHT = True,
parser.add_argument('--files-progress', nargs='?', action=BoolArg, default=False, help='Show files progress', dest='showFilesProgress', choices=('true', 'false')) enableLSD = True, enableUPNP = True, enableNATPMP = True, enableUTP = True, enableTCP = True):
parser.add_argument('--pieces-progress', nargs='?', action=BoolArg, default=False, help='Show pieces progress', dest='showPiecesProgress', choices=('true', 'false')) self.config = Struct()
parser.add_argument('--debug-alerts', nargs='?', action=BoolArg, default=False, help='Show debug alert notifications', dest='debugAlerts', choices=('true', 'false')) self.config.uri = uri
parser.add_argument('--exit-on-finish', nargs='?', action=BoolArg, default=False, help='Exit when download finished', dest='exitOnFinish', choices=('true', 'false')) self.config.bindAddress = bindAddress
parser.add_argument('--resume-file', type=str, default='', help='Use fast resume file', dest='resumeFile') self.config.downloadPath = downloadPath
parser.add_argument('--state-file', type=str, default='', help='Use file for saving/restoring session state', dest='stateFile') self.config.idleTimeout = idleTimeout
parser.add_argument('--user-agent', type=str, default=USER_AGENT, help='Set an user agent', dest='userAgent') self.config.fileIndex = fileIndex
parser.add_argument('--dht-routers', type=str, default='', help='Additional DHT routers (comma-separated host:port pairs)', dest='dhtRouters') self.config.keepComplete = keepComplete
parser.add_argument('--trackers', type=str, default='', help='Additional trackers (comma-separated URLs)', dest='trackers') self.config.keepIncomplete = keepIncomplete
parser.add_argument('--listen-port', type=int, default=6881, help='Use specified port for incoming connections', dest='listenPort') self.config.keepFiles = keepFiles
parser.add_argument('--torrent-connect-boost', type=int, default=50, help='The number of peers to try to connect to immediately when the first tracker response is received for a torrent', dest='torrentConnectBoost') self.config.showAllStats = showAllStats
parser.add_argument('--connection-speed', type=int, default=50, help='The number of peer connection attempts that are made per second', dest='connectionSpeed') self.config.showOverallProgress = showOverallProgress
parser.add_argument('--peer-connect-timeout', type=int, default=15, help='The number of seconds to wait after a connection attempt is initiated to a peer', dest='peerConnectTimeout') self.config.showFilesProgress = showFilesProgress
parser.add_argument('--request-timeout', type=int, default=20, help='The number of seconds until the current front piece request will time out', dest='requestTimeout') self.config.showPiecesProgress = showPiecesProgress
parser.add_argument('--dl-rate', type=int, default=-1, help='Max download rate (kB/s)', dest='maxDownloadRate') self.config.debugAlerts = debugAlerts
parser.add_argument('--ul-rate', type=int, default=-1, help='Max upload rate (kB/s)', dest='maxUploadRate') self.config.exitOnFinish = exitOnFinish
parser.add_argument('--connections-limit', type=int, default=200, help='Set a global limit on the number of connections opened', dest='connectionsLimit') self.config.resumeFile = resumeFile
parser.add_argument('--encryption', type=int, default=1, help='Encryption: 0=forced 1=enabled (default) 2=disabled', dest='encryption') self.config.stateFile = stateFile
parser.add_argument('--min-reconnect-time', type=int, default=60, help='The time to wait between peer connection attempts. If the peer fails, the time is multiplied by fail counter', dest='minReconnectTime') self.config.userAgent = userAgent
parser.add_argument('--max-failcount', type=int, default=3, help='The maximum times we try to connect to a peer before stop connecting again', dest='maxFailCount') self.config.dhtRouters = dhtRouters
parser.add_argument('--no-sparse', nargs='?', action=BoolArg, default=False, help='Do not use sparse file allocation', dest='noSparseFile', choices=('true', 'false')) self.config.trackers = trackers
parser.add_argument('--random-port', nargs='?', action=BoolArg, default=False, help='Use random listen port (49152-65535)', dest='randomPort', choices=('true', 'false')) self.config.listenPort = listenPort
parser.add_argument('--enable-scrape', nargs='?', action=BoolArg, default=False, help='Enable sending scrape request to tracker (updates total peers/seeds count)', dest='enableScrape', choices=('true', 'false')) self.config.torrentConnectBoost = torrentConnectBoost
parser.add_argument('--enable-dht', nargs='?', action=BoolArg, default=True, help='Enable DHT (Distributed Hash Table)', dest='enableDHT', choices=('true', 'false')) self.config.connectionSpeed = connectionSpeed
parser.add_argument('--enable-lsd', nargs='?', action=BoolArg, default=True, help='Enable LSD (Local Service Discovery)', dest='enableLSD', choices=('true', 'false')) self.config.peerConnectTimeout = peerConnectTimeout
parser.add_argument('--enable-upnp', nargs='?', action=BoolArg, default=True, help='Enable UPnP (UPnP port-mapping)', dest='enableUPNP', choices=('true', 'false')) self.config.requestTimeout = requestTimeout
parser.add_argument('--enable-natpmp', nargs='?', action=BoolArg, default=True, help='Enable NATPMP (NAT port-mapping)', dest='enableNATPMP', choices=('true', 'false')) self.config.maxDownloadRate = maxDownloadRate
parser.add_argument('--enable-utp', nargs='?', action=BoolArg, default=True, help='Enable uTP protocol', dest='enableUTP', choices=('true', 'false')) self.config.maxUploadRate = maxUploadRate
parser.add_argument('--enable-tcp', nargs='?', action=BoolArg, default=True, help='Enable TCP protocol', dest='enableTCP', choices=('true', 'false')) self.config.connectionsLimit = connectionsLimit
if params is None: self.config.encryption = encryption
config_ = parser.parse_args() self.config.minReconnectTime = minReconnectTime
else: self.config.maxFailCount = maxFailCount
config_ = parser.parse_args(args = params) self.config.noSparseFile = noSparseFile
self.config = AttributeDict() self.config.randomPort = randomPort
for k in config_.__dict__.keys(): self.config.enableScrape = enableScrape
self.config[k] = config_.__dict__[k] self.config.enableDHT = enableDHT
self.config.enableLSD = enableLSD
self.config.enableUPNP = enableUPNP
self.config.enableNATPMP = enableNATPMP
self.config.enableUTP = enableUTP
self.config.enableTCP = enableTCP
if self.config.uri == '': if self.config.uri == '':
parser.print_usage() raise Exception("uri is empty string")
if STANDALONE:
sys.exit(1)
else:
raise "Invalid argument"
if self.config.uri.startswith('magnet:'): if self.config.uri.startswith('magnet:'):
self.magnet = True self.magnet = True
if self.config.resumeFile is None: self.config.resumeFile = ''
if self.config.resumeFile != '' and not self.config.keepFiles: if self.config.resumeFile != '' and not self.config.keepFiles:
logging.error('Usage of option --resume-file is allowed only along with --keep-files') raise Exception('Не должно быть файла восстановления, если мы не храним файлы')
if STANDALONE:
sys.exit(1)
else:
raise
def buildTorrentParams(self, uri): def buildTorrentParams(self, uri):
if uri[1] == ':' and sys.platform.startswith('win'): if uri[1] == ':' and sys.platform.startswith('win'):
uri = 'file:///' + uri uri = 'file:///' + uri
@ -796,7 +780,7 @@ class Pyrrent2http(object):
self.session.set_settings(settings) self.session.set_settings(settings)
if self.config.stateFile != '': if self.config.stateFile != '':
logging.info('Loading session state from %s', self.config.stateFile) logging.info('Loading session state from %s' % (self.config.stateFile,))
try: try:
with open(self.config.stateFile, 'rb') as f: with open(self.config.stateFile, 'rb') as f:
bytes__ = f.read() bytes__ = f.read()
@ -900,7 +884,7 @@ class Pyrrent2http(object):
'offset': file_.offset, 'offset': file_.offset,
'download': file_.Downloaded(), 'download': file_.Downloaded(),
'progress': file_.Progress(), 'progress': file_.Progress(),
'save_path': file_.SavePath(), 'save_path': file_.save_path,
'url': Url 'url': Url
} }
retFiles['files'].append(fi) retFiles['files'].append(fi)
@ -1019,6 +1003,7 @@ class Pyrrent2http(object):
data = lt.bencode(entry) data = lt.bencode(entry)
logging.info('Saving session state to: %s' % (self.config.stateFile,)) logging.info('Saving session state to: %s' % (self.config.stateFile,))
try: try:
logging.info('Saving session state to: %s' % (self.config.stateFile,))
with open(self.config.stateFile, 'wb') as f: with open(self.config.stateFile, 'wb') as f:
f.write(data) f.write(data)
except IOError as e: except IOError as e:
@ -1044,8 +1029,8 @@ class Pyrrent2http(object):
if self.TorrentFS.HasTorrentInfo(): if self.TorrentFS.HasTorrentInfo():
for file in self.TorrentFS.Files(): for file in self.TorrentFS.Files():
if (not self.config.keepComplete or not file.IsComplete()) and (not self.config.keepIncomplete or file.IsComplete()): if (not self.config.keepComplete or not file.IsComplete()) and (not self.config.keepIncomplete or file.IsComplete()):
if os.path.exists(file.SavePath()): if os.path.exists(file.save_path):
files.append(file.SavePath()) files.append(file.save_path)
return files return files
def removeTorrent(self): def removeTorrent(self):
files = [] files = []

View File

@ -3,6 +3,13 @@ import socket
import chardet import chardet
class Struct(dict):
def __getattr__(self, attr):
return self[attr]
def __setattr__(self, attr, value):
self[attr] = value
def localize_path(path): def localize_path(path):
path = path.decode(chardet.detect(path)['encoding']) path = path.decode(chardet.detect(path)['encoding'])
if not sys.platform.startswith('win'): if not sys.platform.startswith('win'):