|
|
|
@ -115,55 +115,56 @@ class ExternalFD(FragmentFD):
|
|
|
|
|
|
|
|
|
|
self._debug_cmd(cmd)
|
|
|
|
|
|
|
|
|
|
if 'fragments' in info_dict:
|
|
|
|
|
fragment_retries = self.params.get('fragment_retries', 0)
|
|
|
|
|
skip_unavailable_fragments = self.params.get('skip_unavailable_fragments', True)
|
|
|
|
|
|
|
|
|
|
count = 0
|
|
|
|
|
while count <= fragment_retries:
|
|
|
|
|
p = subprocess.Popen(
|
|
|
|
|
cmd, stderr=subprocess.PIPE)
|
|
|
|
|
_, stderr = process_communicate_or_kill(p)
|
|
|
|
|
if p.returncode == 0:
|
|
|
|
|
break
|
|
|
|
|
# TODO: Decide whether to retry based on error code
|
|
|
|
|
# https://aria2.github.io/manual/en/html/aria2c.html#exit-status
|
|
|
|
|
self.to_stderr(stderr.decode('utf-8', 'replace'))
|
|
|
|
|
count += 1
|
|
|
|
|
if count <= fragment_retries:
|
|
|
|
|
self.to_screen(
|
|
|
|
|
'[%s] Got error. Retrying fragments (attempt %d of %s)...'
|
|
|
|
|
% (self.get_basename(), count, self.format_retries(fragment_retries)))
|
|
|
|
|
if count > fragment_retries:
|
|
|
|
|
if not skip_unavailable_fragments:
|
|
|
|
|
self.report_error('Giving up after %s fragment retries' % fragment_retries)
|
|
|
|
|
return -1
|
|
|
|
|
|
|
|
|
|
decrypt_fragment = self.decrypter(info_dict)
|
|
|
|
|
dest, _ = sanitize_open(tmpfilename, 'wb')
|
|
|
|
|
for frag_index, fragment in enumerate(info_dict['fragments']):
|
|
|
|
|
fragment_filename = '%s-Frag%d' % (tmpfilename, frag_index)
|
|
|
|
|
try:
|
|
|
|
|
src, _ = sanitize_open(fragment_filename, 'rb')
|
|
|
|
|
except IOError:
|
|
|
|
|
if skip_unavailable_fragments and frag_index > 1:
|
|
|
|
|
self.to_screen('[%s] Skipping fragment %d ...' % (self.get_basename(), frag_index))
|
|
|
|
|
continue
|
|
|
|
|
self.report_error('Unable to open fragment %d' % frag_index)
|
|
|
|
|
return -1
|
|
|
|
|
dest.write(decrypt_fragment(fragment, src.read()))
|
|
|
|
|
src.close()
|
|
|
|
|
if not self.params.get('keep_fragments', False):
|
|
|
|
|
os.remove(encodeFilename(fragment_filename))
|
|
|
|
|
dest.close()
|
|
|
|
|
os.remove(encodeFilename('%s.frag.urls' % tmpfilename))
|
|
|
|
|
else:
|
|
|
|
|
if 'fragments' not in info_dict:
|
|
|
|
|
p = subprocess.Popen(
|
|
|
|
|
cmd, stderr=subprocess.PIPE)
|
|
|
|
|
_, stderr = process_communicate_or_kill(p)
|
|
|
|
|
if p.returncode != 0:
|
|
|
|
|
self.to_stderr(stderr.decode('utf-8', 'replace'))
|
|
|
|
|
return p.returncode
|
|
|
|
|
return p.returncode
|
|
|
|
|
|
|
|
|
|
fragment_retries = self.params.get('fragment_retries', 0)
|
|
|
|
|
skip_unavailable_fragments = self.params.get('skip_unavailable_fragments', True)
|
|
|
|
|
|
|
|
|
|
count = 0
|
|
|
|
|
while count <= fragment_retries:
|
|
|
|
|
p = subprocess.Popen(
|
|
|
|
|
cmd, stderr=subprocess.PIPE)
|
|
|
|
|
_, stderr = process_communicate_or_kill(p)
|
|
|
|
|
if p.returncode == 0:
|
|
|
|
|
break
|
|
|
|
|
# TODO: Decide whether to retry based on error code
|
|
|
|
|
# https://aria2.github.io/manual/en/html/aria2c.html#exit-status
|
|
|
|
|
self.to_stderr(stderr.decode('utf-8', 'replace'))
|
|
|
|
|
count += 1
|
|
|
|
|
if count <= fragment_retries:
|
|
|
|
|
self.to_screen(
|
|
|
|
|
'[%s] Got error. Retrying fragments (attempt %d of %s)...'
|
|
|
|
|
% (self.get_basename(), count, self.format_retries(fragment_retries)))
|
|
|
|
|
if count > fragment_retries:
|
|
|
|
|
if not skip_unavailable_fragments:
|
|
|
|
|
self.report_error('Giving up after %s fragment retries' % fragment_retries)
|
|
|
|
|
return -1
|
|
|
|
|
|
|
|
|
|
decrypt_fragment = self.decrypter(info_dict)
|
|
|
|
|
dest, _ = sanitize_open(tmpfilename, 'wb')
|
|
|
|
|
for frag_index, fragment in enumerate(info_dict['fragments']):
|
|
|
|
|
fragment_filename = '%s-Frag%d' % (tmpfilename, frag_index)
|
|
|
|
|
try:
|
|
|
|
|
src, _ = sanitize_open(fragment_filename, 'rb')
|
|
|
|
|
except IOError:
|
|
|
|
|
if skip_unavailable_fragments and frag_index > 1:
|
|
|
|
|
self.to_screen('[%s] Skipping fragment %d ...' % (self.get_basename(), frag_index))
|
|
|
|
|
continue
|
|
|
|
|
self.report_error('Unable to open fragment %d' % frag_index)
|
|
|
|
|
return -1
|
|
|
|
|
dest.write(decrypt_fragment(fragment, src.read()))
|
|
|
|
|
src.close()
|
|
|
|
|
if not self.params.get('keep_fragments', False):
|
|
|
|
|
os.remove(encodeFilename(fragment_filename))
|
|
|
|
|
dest.close()
|
|
|
|
|
os.remove(encodeFilename('%s.frag.urls' % tmpfilename))
|
|
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class CurlFD(ExternalFD):
|
|
|
|
|