def vod_event_callback(d, event, params): if event == VODEVENT_START: stream = params["stream"] length = params["length"] mimetype = params["mimetype"] global FIRST_ITERATION, QUIT_NOW, SESSION epoch_server = None epoch_local = time.time() bitrate = None estduration = None currentSize = 0 partialSize = length start = int(config["start"]) end = int(config["end"]) if FIRST_ITERATION: if config["debug"]: print >> sys.stderr, time.asctime(), "-", "main: Seeking to second: ", config[ "start" ], "estimated duration: ", estduration file = None blocksize = d.get_def().get_piece_length() if d.get_def().is_multifile_torrent(): file = d.get_selected_files()[0] bitrate = d.get_def().get_bitrate(file) if bitrate is not None: estduration = float(length) / float(bitrate) if config["debug"]: print >> sys.stderr, time.asctime(), "-", "main: Seeking: bitrate: ", bitrate, "duration: ", estduration if start < int(estduration): seekbyte = float(bitrate * start) # Works only with TS container if mimetype == "video/mp2t": # Ric if it is a ts stream we can round the start # byte to the beginning of a ts packet (ts pkt = 188 bytes) seekbyte = seekbyte - seekbyte % 188 stream.seek(int(seekbyte)) if config["debug"]: print >> sys.stderr, time.asctime(), "-", "main: Seeking: seekbyte: ", seekbyte, "start time: ", config[ "start" ] FIRST_ITERATION = False else: print >> sys.stderr, time.asctime(), "-", "main: Starting time exceeds video duration!!" if end != "": # Determine the final size of the stream depending on the end Time endbyte = float(bitrate * int(config["end"])) partialSize = endbyte - seekbyte else: print >> sys.stderr, time.asctime(), "-", "Seeking to the the beginning" stream.seek(0) basename = config["videoOut"] + ".mpeg" if config["destdir"] == "default download dir": config["destdir"] = get_default_dest_dir() filename = os.path.join(config["destdir"], basename) if config["debug"]: print >> sys.stderr, time.asctime(), "-", "main: Saving the file in the following location: ", filename f = open(filename, "wb") prev_data = None while not FIRST_ITERATION and (currentSize < partialSize): data = stream.read() if config["debug"]: print >> sys.stderr, time.asctime(), "-", "main: VOD ready callback: reading", type(data) print >> sys.stderr, time.asctime(), "-", "main: VOD ready callback: reading", len(data) if len(data) == 0 or data == prev_data: if config["debug"]: print >> sys.stderr, time.asctime(), "-", "main: Same data replicated: we reached the end of the stream" break f.write(data) currentSize += len(data) prev_data = data # Stop the download if not config["continueDownload"]: # SESSION.remove_ d.stop() # seek(0) if config["quitAfter"]: QUIT_NOW = True f.close() stream.close() print >> sys.stderr, time.asctime(), "-", "main: Seeking: END!!" if config["createNewTorr"]: createTorr(filename)
def __init__(self, scfg=None, ignore_singleton=False): """ A Session object is created which is configured following a copy of the SessionStartupConfig scfg. (copy constructor used internally) @param scfg SessionStartupConfig object or None, in which case we look for a saved session in the default location (state dir). If we can't find it, we create a new SessionStartupConfig() object to serve as startup config. Next, the config is saved in the directory indicated by its 'state_dir' attribute. In the current implementation only a single session instance can exist at a time in a process. The ignore_singleton flag is used for testing. """ if not ignore_singleton: if Session.__single: raise RuntimeError, "Session is singleton" Session.__single = self self.sesslock = RLock() # Determine startup config to use if scfg is None: # If no override try: # Then try to read from default location state_dir = Session.get_default_state_dir() cfgfilename = Session.get_default_config_filename(state_dir) scfg = SessionStartupConfig.load(cfgfilename) except: # If that fails, create a fresh config with factory defaults print_exc() scfg = SessionStartupConfig() self.sessconfig = scfg.sessconfig else: # overrides any saved config # Work from copy self.sessconfig = copy.copy(scfg.sessconfig) #SmoothIT_ self._is_supporter_seed = False self._supporter_ips = [] #_SmoothIT # Create dir for session state, if not exist state_dir = self.sessconfig['state_dir'] if state_dir is None: state_dir = Session.get_default_state_dir() self.sessconfig['state_dir'] = state_dir if not os.path.isdir(state_dir): os.makedirs(state_dir) collected_torrent_dir = self.sessconfig['torrent_collecting_dir'] if not collected_torrent_dir: collected_torrent_dir = os.path.join(self.sessconfig['state_dir'], STATEDIR_TORRENTCOLL_DIR) self.sessconfig['torrent_collecting_dir'] = collected_torrent_dir if not os.path.exists(collected_torrent_dir): os.makedirs(collected_torrent_dir) if not self.sessconfig['peer_icon_path']: self.sessconfig['peer_icon_path'] = os.path.join( self.sessconfig['state_dir'], STATEDIR_PEERICON_DIR) # PERHAPS: load default TorrentDef and DownloadStartupConfig from state dir # Let user handle that, he's got default_state_dir, etc. # Core init #print >>sys.stderr,'Session: __init__ config is', self.sessconfig if GOTM2CRYPTO: permidmod.init() # # Set params that depend on state_dir # # 1. keypair # pairfilename = os.path.join(self.sessconfig['state_dir'], 'ec.pem') if self.sessconfig['eckeypairfilename'] is None: self.sessconfig['eckeypairfilename'] = pairfilename if os.access(self.sessconfig['eckeypairfilename'], os.F_OK): # May throw exceptions self.keypair = permidmod.read_keypair( self.sessconfig['eckeypairfilename']) else: self.keypair = permidmod.generate_keypair() # Save keypair pubfilename = os.path.join(self.sessconfig['state_dir'], 'ecpub.pem') permidmod.save_keypair(self.keypair, pairfilename) permidmod.save_pub_key(self.keypair, pubfilename) # 2. Downloads persistent state dir dlpstatedir = os.path.join(self.sessconfig['state_dir'], STATEDIR_DLPSTATE_DIR) if not os.path.isdir(dlpstatedir): os.mkdir(dlpstatedir) # 3. tracker trackerdir = self.get_internal_tracker_dir() if not os.path.isdir(trackerdir): os.mkdir(trackerdir) if self.sessconfig['tracker_dfile'] is None: self.sessconfig['tracker_dfile'] = os.path.join( trackerdir, 'tracker.db') if self.sessconfig['tracker_allowed_dir'] is None: self.sessconfig['tracker_allowed_dir'] = trackerdir if self.sessconfig['tracker_logfile'] is None: if sys.platform == "win32": # Not "Nul:" but "nul" is /dev/null on Win32 sink = 'nul' else: sink = '/dev/null' self.sessconfig['tracker_logfile'] = sink # 4. superpeer.txt and crawler.txt if self.sessconfig['superpeer_file'] is None: self.sessconfig['superpeer_file'] = os.path.join( self.sessconfig['install_dir'], LIBRARYNAME, 'Core', 'superpeer.txt') if 'crawler_file' not in self.sessconfig or self.sessconfig[ 'crawler_file'] is None: self.sessconfig['crawler_file'] = os.path.join( self.sessconfig['install_dir'], LIBRARYNAME, 'Core', 'Statistics', 'crawler.txt') # 5. download_help_dir if self.sessconfig['overlay'] and self.sessconfig['download_help']: if self.sessconfig['download_help_dir'] is None: self.sessconfig['download_help_dir'] = os.path.join( get_default_dest_dir(), DESTDIR_COOPDOWNLOAD) # Jelle: under linux, default_dest_dir can be /tmp. Then download_help_dir can be deleted inbetween # sessions. if not os.path.isdir(self.sessconfig['download_help_dir']): os.makedirs(self.sessconfig['download_help_dir']) # 6. peer_icon_path if self.sessconfig['peer_icon_path'] is None: self.sessconfig['peer_icon_path'] = os.path.join( self.sessconfig['state_dir'], STATEDIR_PEERICON_DIR) if not os.path.isdir(self.sessconfig['peer_icon_path']): os.mkdir(self.sessconfig['peer_icon_path']) # 7. Poor man's versioning of SessionConfig, add missing # default values. Really should use PERSISTENTSTATE_CURRENTVERSION # and do conversions. for key, defvalue in sessdefaults.iteritems(): if key not in self.sessconfig: self.sessconfig[key] = defvalue if not 'live_aux_seeders' in self.sessconfig: # Poor man's versioning, really should update PERSISTENTSTATE_CURRENTVERSION self.sessconfig['live_aux_seeders'] = sessdefaults[ 'live_aux_seeders'] if not 'nat_detect' in self.sessconfig: self.sessconfig['nat_detect'] = sessdefaults['nat_detect'] if not 'puncturing_internal_port' in self.sessconfig: self.sessconfig['puncturing_internal_port'] = sessdefaults[ 'puncturing_internal_port'] if not 'stun_servers' in self.sessconfig: self.sessconfig['stun_servers'] = sessdefaults['stun_servers'] if not 'pingback_servers' in self.sessconfig: self.sessconfig['pingback_servers'] = sessdefaults[ 'pingback_servers'] if not 'mainline_dht' in self.sessconfig: self.sessconfig['mainline_dht'] = sessdefaults['mainline_dht'] # Checkpoint startup config self.save_pstate_sessconfig() # Create handler for calling back the user via separate threads self.uch = UserCallbackHandler(self) # Create engine with network thread self.lm = TriblerLaunchMany() self.lm.register(self, self.sesslock) self.lm.start()
def __init__(self,scfg=None,ignore_singleton=False): """ A Session object is created which is configured following a copy of the SessionStartupConfig scfg. (copy constructor used internally) @param scfg SessionStartupConfig object or None, in which case we look for a saved session in the default location (state dir). If we can't find it, we create a new SessionStartupConfig() object to serve as startup config. Next, the config is saved in the directory indicated by its 'state_dir' attribute. In the current implementation only a single session instance can exist at a time in a process. The ignore_singleton flag is used for testing. """ if not ignore_singleton: if Session.__single: raise RuntimeError, "Session is singleton" Session.__single = self self.sesslock = RLock() # Determine startup config to use if scfg is None: # If no override try: # Then try to read from default location state_dir = Session.get_default_state_dir() cfgfilename = Session.get_default_config_filename(state_dir) scfg = SessionStartupConfig.load(cfgfilename) except: # If that fails, create a fresh config with factory defaults print_exc() scfg = SessionStartupConfig() self.sessconfig = scfg.sessconfig else: # overrides any saved config # Work from copy self.sessconfig = copy.copy(scfg.sessconfig) # Create dir for session state, if not exist state_dir = self.sessconfig['state_dir'] if state_dir is None: state_dir = Session.get_default_state_dir() self.sessconfig['state_dir'] = state_dir if not os.path.isdir(state_dir): os.makedirs(state_dir) collected_torrent_dir = self.sessconfig['torrent_collecting_dir'] if not collected_torrent_dir: collected_torrent_dir = os.path.join(self.sessconfig['state_dir'], STATEDIR_TORRENTCOLL_DIR) self.sessconfig['torrent_collecting_dir'] = collected_torrent_dir collected_subtitles_dir = self.sessconfig.get('subtitles_collecting_dir',None) if not collected_subtitles_dir: collected_subtitles_dir = os.path.join(self.sessconfig['state_dir'], STATEDIR_SUBSCOLL_DIR) self.sessconfig['subtitles_collecting_dir'] = collected_subtitles_dir if not os.path.exists(collected_torrent_dir): os.makedirs(collected_torrent_dir) if not self.sessconfig['peer_icon_path']: self.sessconfig['peer_icon_path'] = os.path.join(self.sessconfig['state_dir'], STATEDIR_PEERICON_DIR) # PERHAPS: load default TorrentDef and DownloadStartupConfig from state dir # Let user handle that, he's got default_state_dir, etc. # Core init #print >>sys.stderr,time.asctime(),'-', 'Session: __init__ config is', self.sessconfig if GOTM2CRYPTO: permidmod.init() # # Set params that depend on state_dir # # 1. keypair # pairfilename = os.path.join(self.sessconfig['state_dir'],'ec.pem') if self.sessconfig['eckeypairfilename'] is None: self.sessconfig['eckeypairfilename'] = pairfilename if os.access(self.sessconfig['eckeypairfilename'],os.F_OK): # May throw exceptions self.keypair = permidmod.read_keypair(self.sessconfig['eckeypairfilename']) else: self.keypair = permidmod.generate_keypair() # Save keypair pubfilename = os.path.join(self.sessconfig['state_dir'],'ecpub.pem') permidmod.save_keypair(self.keypair,pairfilename) permidmod.save_pub_key(self.keypair,pubfilename) # 2. Downloads persistent state dir dlpstatedir = os.path.join(self.sessconfig['state_dir'],STATEDIR_DLPSTATE_DIR) if not os.path.isdir(dlpstatedir): os.mkdir(dlpstatedir) # 3. tracker trackerdir = self.get_internal_tracker_dir() if not os.path.isdir(trackerdir): os.mkdir(trackerdir) if self.sessconfig['tracker_dfile'] is None: self.sessconfig['tracker_dfile'] = os.path.join(trackerdir,'tracker.db') if self.sessconfig['tracker_allowed_dir'] is None: self.sessconfig['tracker_allowed_dir'] = trackerdir if self.sessconfig['tracker_logfile'] is None: if sys.platform == "win32": # Not "Nul:" but "nul" is /dev/null on Win32 sink = 'nul' else: sink = '/dev/null' self.sessconfig['tracker_logfile'] = sink # 4. superpeer.txt and crawler.txt if self.sessconfig['superpeer_file'] is None: self.sessconfig['superpeer_file'] = os.path.join(self.sessconfig['install_dir'],LIBRARYNAME,'Core','superpeer.txt') if 'crawler_file' not in self.sessconfig or self.sessconfig['crawler_file'] is None: self.sessconfig['crawler_file'] = os.path.join(self.sessconfig['install_dir'], LIBRARYNAME,'Core','Statistics','crawler.txt') # 5. download_help_dir if self.sessconfig['overlay'] and self.sessconfig['download_help']: if self.sessconfig['download_help_dir'] is None: self.sessconfig['download_help_dir'] = os.path.join(get_default_dest_dir(),DESTDIR_COOPDOWNLOAD) # Jelle: under linux, default_dest_dir can be /tmp. Then download_help_dir can be deleted inbetween # sessions. if not os.path.isdir(self.sessconfig['download_help_dir']): os.makedirs(self.sessconfig['download_help_dir']) # 6. peer_icon_path if self.sessconfig['peer_icon_path'] is None: self.sessconfig['peer_icon_path'] = os.path.join(self.sessconfig['state_dir'],STATEDIR_PEERICON_DIR) if not os.path.isdir(self.sessconfig['peer_icon_path']): os.mkdir(self.sessconfig['peer_icon_path']) # 7. Poor man's versioning of SessionConfig, add missing # default values. Really should use PERSISTENTSTATE_CURRENTVERSION # and do conversions. for key,defvalue in sessdefaults.iteritems(): if key not in self.sessconfig: self.sessconfig[key] = defvalue if not 'live_aux_seeders' in self.sessconfig: # Poor man's versioning, really should update PERSISTENTSTATE_CURRENTVERSION self.sessconfig['live_aux_seeders'] = sessdefaults['live_aux_seeders'] if not 'nat_detect' in self.sessconfig: self.sessconfig['nat_detect'] = sessdefaults['nat_detect'] if not 'puncturing_internal_port' in self.sessconfig: self.sessconfig['puncturing_internal_port'] = sessdefaults['puncturing_internal_port'] if not 'stun_servers' in self.sessconfig: self.sessconfig['stun_servers'] = sessdefaults['stun_servers'] if not 'pingback_servers' in self.sessconfig: self.sessconfig['pingback_servers'] = sessdefaults['pingback_servers'] if not 'mainline_dht' in self.sessconfig: self.sessconfig['mainline_dht'] = sessdefaults['mainline_dht'] # Checkpoint startup config self.save_pstate_sessconfig() # Create handler for calling back the user via separate threads self.uch = UserCallbackHandler(self) # Create engine with network thread self.lm = TriblerLaunchMany() self.lm.register(self,self.sesslock) self.lm.start()
def vod_event_callback(d, event, params): if event == VODEVENT_START: stream = params["stream"] length = params["length"] mimetype = params["mimetype"] global FIRST_ITERATION, QUIT_NOW, SESSION epoch_server = None epoch_local = time.time() bitrate = None estduration = None currentSize = 0 partialSize = length start = int(config['start']) end = int(config['end']) if FIRST_ITERATION: if config['debug']: print >> sys.stderr, "main: Seeking to second: ", config[ 'start'], "estimated duration: ", estduration file = None blocksize = d.get_def().get_piece_length() if d.get_def().is_multifile_torrent(): file = d.get_selected_files()[0] bitrate = d.get_def().get_bitrate(file) if bitrate is not None: estduration = float(length) / float(bitrate) if config['debug']: print >> sys.stderr, "main: Seeking: bitrate: ", bitrate, "duration: ", estduration if start < int(estduration): seekbyte = float(bitrate * start) # Works only with TS container if mimetype == 'video/mp2t': # Ric if it is a ts stream we can round the start # byte to the beginning of a ts packet (ts pkt = 188 bytes) seekbyte = seekbyte - seekbyte % 188 stream.seek(int(seekbyte)) if config['debug']: print >> sys.stderr, "main: Seeking: seekbyte: ", seekbyte, "start time: ", config[ 'start'] FIRST_ITERATION = False else: print >> sys.stderr, "main: Starting time exceeds video duration!!" if end != '': # Determine the final size of the stream depending on the end Time endbyte = float(bitrate * int(config['end'])) partialSize = endbyte - seekbyte else: print >> sys.stderr, "Seeking to the the beginning" stream.seek(0) basename = config['videoOut'] + '.mpeg' if config['destdir'] == 'default download dir': config['destdir'] = get_default_dest_dir() filename = os.path.join(config['destdir'], basename) if config['debug']: print >> sys.stderr, "main: Saving the file in the following location: ", filename f = open(filename, "wb") prev_data = None while not FIRST_ITERATION and (currentSize < partialSize): data = stream.read() if config['debug']: print >> sys.stderr, "main: VOD ready callback: reading", type( data) print >> sys.stderr, "main: VOD ready callback: reading", len( data) if len(data) == 0 or data == prev_data: if config['debug']: print >> sys.stderr, "main: Same data replicated: we reached the end of the stream" break f.write(data) currentSize += len(data) prev_data = data # Stop the download if not config['continueDownload']: #SESSION.remove_ d.stop() #seek(0) if config['quitAfter']: QUIT_NOW = True f.close() stream.close() print >> sys.stderr, "main: Seeking: END!!" if config['createNewTorr']: createTorr(filename)