diff --git a/lib/pyrrent2http/engine.py b/lib/pyrrent2http/engine.py index 1f2417a..730d057 100644 --- a/lib/pyrrent2http/engine.py +++ b/lib/pyrrent2http/engine.py @@ -3,21 +3,23 @@ import json import os import socket import stat -import subprocess import sys import time import urllib2 import httplib from os.path import dirname -from download import LibraryManager +#from download import LibraryManager -import logpipe +import pyrrent2http + +#import logpipe import mimetypes import xbmc from error import Error from platform import Platform from . import SessionStatus, FileStatus, PeerInfo, MediaType, Encryption from util import can_bind, find_free_port, ensure_fs_encoding +import threading class Engine: @@ -198,7 +200,7 @@ class Engine: self.logger = logger self.uri = uri self.logpipe = None - self.process = None +# self.process = None self.started = False @staticmethod @@ -239,47 +241,47 @@ class Engine: self.bind_port = port kwargs = { - 'bind': "%s:%s" % (self.bind_host, self.bind_port), - 'uri': self.uri, - 'file-index': start_index, - 'dl-path': download_path, - 'connections-limit': self.connections_limit, - 'dl-rate': self.download_kbps, - 'ul-rate': self.upload_kbps, - 'enable-dht': self.enable_dht, - 'enable-lsd': self.enable_lsd, - 'enable-natpmp': self.enable_natpmp, - 'enable-upnp': self.enable_upnp, - 'enable-scrape': self.enable_scrape, - 'encryption': self.encryption, - 'show-stats': self.log_stats, - 'files-progress': self.log_files_progress, - 'overall-progress': self.log_overall_progress, - 'pieces-progress': self.log_pieces_progress, - 'listen-port': self.listen_port, - 'random-port': self.use_random_port, - 'keep-complete': self.keep_complete, - 'keep-incomplete': self.keep_incomplete, - 'keep-files': self.keep_files, - 'max-idle': self.max_idle_timeout, - 'no-sparse': self.no_sparse, - 'resume-file': self.resume_file, - 'user-agent': self.user_agent, - 'state-file': self.state_file, - 'enable-utp': self.enable_utp, - 'enable-tcp': self.enable_tcp, - 'debug-alerts': self.debug_alerts, - 'torrent-connect-boost': self.torrent_connect_boost, - 'connection-speed': self.connection_speed, - 'peer-connect-timeout': self.peer_connect_timeout, - 'request-timeout': self.request_timeout, - 'min-reconnect-time': self.min_reconnect_time, - 'max-failcount': self.max_failcount, - 'dht-routers': ",".join(self.dht_routers), - 'trackers': ",".join(self.trackers), + '--bind': "%s:%s" % (self.bind_host, self.bind_port), + '--uri': self.uri, + '--file-index': start_index, + '--dl-path': download_path, + '--connections-limit': self.connections_limit, + '--dl-rate': self.download_kbps, + '--ul-rate': self.upload_kbps, + '--enable-dht': self.enable_dht, + '--enable-lsd': self.enable_lsd, + '--enable-natpmp': self.enable_natpmp, + '--enable-upnp': self.enable_upnp, + '--enable-scrape': self.enable_scrape, + '--encryption': self.encryption, + '--show-stats': self.log_stats, + '--files-progress': self.log_files_progress, + '--overall-progress': self.log_overall_progress, + '--pieces-progress': self.log_pieces_progress, + '--listen-port': self.listen_port, + '--random-port': self.use_random_port, + '--keep-complete': self.keep_complete, + '--keep-incomplete': self.keep_incomplete, + '--keep-files': self.keep_files, + '--max-idle': self.max_idle_timeout, + '--no-sparse': self.no_sparse, + '--resume-file': self.resume_file, + '--user-agent': self.user_agent, + '--state-file': self.state_file, + '--enable-utp': self.enable_utp, + '--enable-tcp': self.enable_tcp, + '--debug-alerts': self.debug_alerts, + '--torrent-connect-boost': self.torrent_connect_boost, + '--connection-speed': self.connection_speed, + '--peer-connect-timeout': self.peer_connect_timeout, + '--request-timeout': self.request_timeout, + '--min-reconnect-time': self.min_reconnect_time, + '--max-failcount': self.max_failcount, + '--dht-routers': ",".join(self.dht_routers), + '--trackers': ",".join(self.trackers), } - args = [binary_path] + args = [] for k, v in kwargs.iteritems(): if v is not None: if isinstance(v, bool): @@ -295,18 +297,37 @@ class Engine: v = str(v) args.append(v) - self._log("Invoking %s" % " ".join(args)) - startupinfo = None - if self.platform.system == "windows": - startupinfo = subprocess.STARTUPINFO() - startupinfo.dwFlags |= 1 - startupinfo.wShowWindow = 0 + self._log("Invoking pyrrent2http") + class Logging(object): + def __init__(self, _log): + self._log = _log + def info(self, message): + self._log('INFO: %s' % (message,)) + def error(self, message): + self._log('ERROR: %s' % (message,)) + 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.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.parseFlags(kwargs) + self.pyrrent2http.startSession() + self.pyrrent2http.startServices() + self.pyrrent2http.addTorrent() + self.pyrrent2http.startHTTP() + self.pyrrent2http_loop = threading.Thread(target = self.pyrrent2http.loop, args = (False,)) + self.pyrrent2http_loop.start() + start = time.time() self.started = True @@ -418,7 +439,7 @@ class Engine: return [PeerInfo(**p) for p in peers] def is_alive(self): - return self.process and self.process.poll() is None + return self.pyrrent2http_loop.is_alive() @staticmethod def _decode(response): @@ -427,7 +448,7 @@ class Engine: except (KeyError, ValueError), e: raise Error("Can't decode response from pyrrent2http: %r" % e, Error.REQUEST_ERROR) - def _request(self, cmd, timeout=None): + __to_del = '''def _request(self, cmd, timeout=None): if not self.started: raise Error("pyrrent2http is not started", Error.REQUEST_ERROR) try: @@ -446,7 +467,7 @@ class Engine: 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): """ By default, close() method sends shutdown command to pyrrent2http, stops logging and returns immediately, not diff --git a/lib/pyrrent2http/pyrrent2http.py b/lib/pyrrent2http/pyrrent2http.py index 89d37be..a56f922 100644 --- a/lib/pyrrent2http/pyrrent2http.py +++ b/lib/pyrrent2http/pyrrent2http.py @@ -2,7 +2,6 @@ # -*- coding: utf-8 -*- import argparse import sys, os -import logging import json try: import libtorrent as lt @@ -21,7 +20,6 @@ import platform import BaseHTTPServer import SocketServer import threading -import signal import io import socket @@ -635,7 +633,7 @@ class Pyrrent2http(object): self.forceShutdown = False self.session = None self.magnet = False - def parseFlags(self): + def parseFlags(self, params = None): parser = argparse.ArgumentParser(add_help=True, version=VERSION) parser.add_argument('--uri', type=str, default='', help='Magnet URI or .torrent file URL', dest='uri') parser.add_argument('--bind', type=str, default='localhost:5001', help='Bind address of torrent2http', dest='bindAddress') @@ -676,7 +674,10 @@ class Pyrrent2http(object): parser.add_argument('--enable-natpmp', nargs='?', action=BoolArg, default=True, help='Enable NATPMP (NAT port-mapping)', dest='enableNATPMP', choices=('true', 'false')) parser.add_argument('--enable-utp', nargs='?', action=BoolArg, default=True, help='Enable uTP protocol', dest='enableUTP', choices=('true', 'false')) parser.add_argument('--enable-tcp', nargs='?', action=BoolArg, default=True, help='Enable TCP protocol', dest='enableTCP', choices=('true', 'false')) - config_ = parser.parse_args() + if params is None: + config_ = parser.parse_args() + else: + config_ = parser.parse_args(args = params) self.config = AttributeDict() for k in config_.__dict__.keys(): self.config[k] = config_.__dict__[k] @@ -688,7 +689,6 @@ class Pyrrent2http(object): if self.config.resumeFile != '' and not self.config.keepFiles: logging.error('Usage of option --resume-file is allowed only along with --keep-files') sys.exit(1) - def buildTorrentParams(self, uri): fileUri = urlparse.urlparse(uri) torrentParams = {} @@ -931,10 +931,12 @@ class Pyrrent2http(object): alert = self.session.pop_alert() if isinstance(alert, alertClass): return alert - def loop(self): + def loop(self, standalone = True): def sigterm_handler(_signo, _stack_frame): self.forceShutdown = True - signal.signal(signal.SIGTERM, sigterm_handler) + if standalone: + import signal + signal.signal(signal.SIGTERM, sigterm_handler) self.statsTicker = Ticker(30) self.saveResumeDataTicker = Ticker(5) time_start = time.time() @@ -1026,6 +1028,7 @@ class Pyrrent2http(object): self.removeFiles(files) def shutdown(self): logging.info('Stopping pyrrent2http...') + self.forceShutdown = True self.statsTicker.stop() self.saveResumeDataTicker.stop() self.httpListener.shutdown() @@ -1043,8 +1046,11 @@ class Pyrrent2http(object): logging.info('Bye bye') sys.exit(0) + + if __name__ == '__main__': try: + import logging pyrrent2http = Pyrrent2http() pyrrent2http.parseFlags()