libzypp  17.22.0
downloader.cc
Go to the documentation of this file.
6 #include <zypp/zyppng/base/Timer>
7 #include <zypp/zyppng/base/EventDispatcher>
8 #include <zypp/Pathname.h>
11 #include <zypp/ByteCount.h>
12 #include <zypp/base/String.h>
13 #include <zypp/PathInfo.h>
14 #include <zypp/media/CurlHelper.h>
16 #include <zypp/ZConfig.h>
17 #include <zypp/base/Logger.h>
18 
19 #include <queue>
20 #include <fcntl.h>
21 #include <iostream>
22 #include <fstream>
23 
24 #define BLKSIZE 131072
25 
26 namespace {
27  bool looks_like_metalink_data( const std::vector<char> &data )
28  {
29  if ( data.empty() )
30  return false;
31 
32  const char *p = data.data();
33  while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n')
34  p++;
35 
36  if (!strncasecmp(p, "<?xml", 5))
37  {
38  while (*p && *p != '>')
39  p++;
40  if (*p == '>')
41  p++;
42  while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n')
43  p++;
44  }
45  bool ret = !strncasecmp( p, "<metalink", 9 ) ? true : false;
46  return ret;
47  }
48 
49  bool looks_like_metalink_file( const zypp::Pathname &file )
50  {
51  std::unique_ptr<FILE, decltype(&fclose)> fd( fopen( file.c_str(), "r" ), &fclose );
52  if ( !fd )
53  return false;
54  return looks_like_metalink_data( zyppng::peek_data_fd( fd.get(), 0, 256 ) );
55  }
56 }
57 
58 namespace zyppng {
59 
60  DownloadPrivate::DownloadPrivate(Downloader &parent, std::shared_ptr<NetworkRequestDispatcher> requestDispatcher, Url &&file, zypp::filesystem::Pathname &&targetPath, zypp::ByteCount &&expectedFileSize )
61  : _requestDispatcher ( requestDispatcher )
62  , _url( std::move(file) )
63  , _targetPath( std::move(targetPath) )
64  , _expectedFileSize( std::move(expectedFileSize) )
65  , _parent( &parent )
66  { }
67 
69  {
70  _sigStartedConn = sigStarted().connect ( sigc::mem_fun( dl, &DownloadPrivate::onRequestStarted) );
71  _sigProgressConn = sigProgress().connect( sigc::mem_fun( dl, &DownloadPrivate::onRequestProgress) );
72  _sigFinishedConn = sigFinished().connect( sigc::mem_fun( dl, &DownloadPrivate::onRequestFinished) );
73  }
74 
76  {
77  _sigStartedConn.disconnect();
78  _sigProgressConn.disconnect();
79  _sigFinishedConn.disconnect();
80  }
81 
83  {
87  return;
88 
89  //reset state variables
90  _isMultiDownload = false;
92  _multiPartMirrors.clear();
94  _blockIter = 0;
95  _errorString = std::string();
97 
99 
102  setFailed( "Failed to read settings from URL " );
103  return;
104  }
105 
106  std::shared_ptr<Request> initialRequest = std::make_shared<Request>( internal::clearQueryString(_url), _targetPath );
107 
108  initialRequest->_originalUrl = _url;
109  initialRequest->transferSettings() = _transferSettings;
110 
111  if ( _isMultiPartEnabled ) {
112  if ( !_checkExistsOnly )
113  initialRequest->transferSettings().addHeader("Accept: */*, application/metalink+xml, application/metalink4+xml");
114  else
115  WAR << "Ignoring enabled multi part option for check only download of : " << internal::clearQueryString(_url) << std::endl;
116  }
117 
118  if ( _checkExistsOnly )
119  initialRequest->setOptions( initialRequest->options() | NetworkRequest::HeadRequest );
120 
121  addNewRequest( initialRequest );
122  }
123 
125  {
126  if ( _state == newState )
127  return;
128  _state = newState;
129  _sigStateChanged.emit( *z_func(), newState );
130  }
131 
133  {
135  _sigStarted.emit( *z_func() );
136  }
137 
138  void DownloadPrivate::onRequestProgress( NetworkRequest &req, off_t dltotal, off_t dlnow, off_t , off_t )
139  {
140  //we are not sure yet if we are downloading a Metalink, for now just send alive messages
141  if ( _state == Download::Initializing ) {
142  if ( !_isMultiPartEnabled ) {
144  } else {
145  if ( !_isMultiDownload ) {
146  std::string cType = req.contentType();
147  if ( cType.find("application/metalink+xml") == 0 || cType.find("application/metalink4+xml") == 0 )
148  _isMultiDownload = true;
149  }
150 
151  if ( !_isMultiDownload && dlnow < 256 ) {
152  // can't tell yet, ...
153  return _sigAlive.emit( *z_func(), dlnow );
154  }
155 
156  if ( !_isMultiDownload )
157  {
158  _isMultiDownload = looks_like_metalink_data( req.peekData( 0, 256 ) );
159  }
160 
161  if ( _isMultiDownload )
162  {
163  // this is a metalink file change the expected filesize
164  if ( zypp::ByteCount( 2, zypp::ByteCount::MB) < static_cast<zypp::ByteCount::SizeType>( dlnow ) ) {
166  return;
167  }
168  return _sigAlive.emit( *z_func(), dlnow );
169  }
170 
171  //if we reach here we have a normal file ( or a multi download with more than 256 byte of comment in the beginning )
173  }
174  }
175 
176  if ( _state == Download::Running ) {
177  if ( _expectedFileSize > 0 && _expectedFileSize < dlnow ) {
179  return;
180  }
181  return _sigProgress.emit( *z_func(), dltotal, dlnow );
182 
183  } else if ( _state == Download::RunningMulti ) {
184  off_t dlnowMulti = _downloadedMultiByteCount;
185  for( const auto &req : _runningRequests ) {
186  dlnowMulti += req->downloadedByteCount();
187  }
188  _sigProgress.emit( *z_func(), _blockList.getFilesize(), dlnowMulti );
189  }
190  }
191 
193  {
194 
195  auto it = std::find_if( _runningRequests.begin(), _runningRequests.end(), [ &req ]( const std::shared_ptr<Request> &r ) {
196  return ( r.get() == &req );
197  });
198  if ( it == _runningRequests.end() )
199  return;
200 
201  auto reqLocked = *it;
202 
203  //remove from running
204  _runningRequests.erase( it );
205 
206  if ( err.isError() ) {
207 
208  bool retry = false;
209 
210  //Handle the auth errors explicitely, we need to give the user a way to put in new credentials
211  //if we get valid new credentials we can retry the request
213 
215  auto authDataPtr = cm.getCred( req.url() );
216 
217  // get stored credentials
218  NetworkAuthData_Ptr cmcred( authDataPtr ? new NetworkAuthData( *authDataPtr ) : new NetworkAuthData() );
220 
221  // We got credentials from store, _triedCredFromStore makes sure we just try the auth from store once
222  if ( cmcred && !reqLocked->_triedCredFromStore ) {
223  DBG << "got stored credentials:" << std::endl << *cmcred << std::endl;
224  ts.setUsername( cmcred->username() );
225  ts.setPassword( cmcred->password() );
226  retry = true;
227  reqLocked->_triedCredFromStore = true;
228  } else {
229 
230  //we did not get credentials from the store, emit a signal that allows
231  //setting new auth data
232 
233  NetworkAuthData credFromUser;
234  credFromUser.setUrl( req.url() );
235 
236  //in case we got a auth hint from the server the error object will contain it
237  auto authHintIt = err.extraInfo().find("authHint");
238  std::string authHint;
239 
240  if ( authHintIt != err.extraInfo().end() ){
241  try {
242  authHint = boost::any_cast<std::string>( authHintIt->second );
243  } catch ( const boost::bad_any_cast &) { }
244  }
245 
246  //preset from store if we found something
247  if ( cmcred && !cmcred->username().empty() )
248  credFromUser.setUsername( cmcred->username() );
249 
250  _sigAuthRequired.emit( *z_func(), credFromUser, authHint );
251  if ( credFromUser.valid() ) {
252  ts.setUsername( credFromUser.username() );
253  ts.setPassword( credFromUser.password() );
254 
255  // set available authentication types from the error
256  if ( credFromUser.authType() == CURLAUTH_NONE )
257  credFromUser.setAuthType( authHint );
258 
259  // set auth type (seems this must be set _after_ setting the userpwd)
260  if ( credFromUser.authType() != CURLAUTH_NONE ) {
261  // FIXME: only overwrite if not empty?
262  req.transferSettings().setAuthType(credFromUser.authTypeAsString());
263  }
264 
265  cm.addCred( credFromUser );
266  cm.save();
267 
268  retry = true;
269  }
270  }
271  } else if ( _state == Download::RunningMulti ) {
272 
273  //if a error happens during a multi download we try to use another mirror to download the failed block
274  DBG << "Request failed " << reqLocked->_myBlock << " " << reqLocked->extendedErrorString() << std::endl;
275  NetworkRequestError dummyErr;
276 
277  //try to init a new multi request, if we have leftover mirrors we get a valid one
278  auto newReq = initMultiRequest( reqLocked->_myBlock, dummyErr );
279  if ( newReq ) {
280  newReq->_retryCount = reqLocked->_retryCount + 1;
281  addNewRequest( newReq );
282  return;
283  } else {
284  //no mirrors left but if we still have running requests, there is hope to finish the block
285  if ( !_runningRequests.empty() ) {
286  DBG << "Adding to failed blocklist " << reqLocked->_myBlock <<std::endl;
287  _failedBlocks.push_back( FailedBlock{ reqLocked->_myBlock, reqLocked->_retryCount, err } );
288  return;
289  }
290  }
291  }
292 
293  //if rety is true we just enqueue the request again, usually this means authentication was updated
294  if ( retry ) {
295  //make sure this request will run asap
296  reqLocked->setPriority( NetworkRequest::High );
297 
298  //this is not a new request, only add to queues but do not connect signals again
299  _runningRequests.push_back( reqLocked );
300  _requestDispatcher->enqueue( reqLocked );
301  return;
302  }
303 
304  //we do not have more mirrors left we can try or we do not have a multi download, abort
305  while( _runningRequests.size() ) {
306  auto req = _runningRequests.back();
307  req->disconnectSignals();
308  _runningRequests.pop_back();
309  _requestDispatcher->cancel( *req, err );
310  }
311 
312  //not all hope is lost, maybe a normal download can work out?
313  if ( _state == Download::RunningMulti ) {
314  //fall back to normal download
315  DBG << "Falling back to download from initial URL." << std::endl;
316  _isMultiDownload = false;
317  _isMultiPartEnabled = false;
319 
320  auto req = std::make_shared<Request>( internal::clearQueryString(_url), _targetPath ) ;
322  addNewRequest( req );
323  return;
324  }
325 
326  _requestError = err;
327  setFailed( "Download failed ");
328  return;
329  }
330 
333  _isMultiDownload = looks_like_metalink_file( req.targetFilePath() );
334  if ( !_isMultiDownload ) {
335  setFinished();
336  return;
337  }
338 
339  DBG << " Upgrading request for URL: "<< req.url() << " to multipart download " << std::endl;
340 
341  //we have a metalink download, lets parse it and see what we got
342  _multiPartMirrors.clear();
343 
344  try {
346  parser.parse( req.targetFilePath() );
347 
348  _blockList = parser.getBlockList();
349 
350  //migrate some settings from the base url to the mirror
351  std::vector<Url> urllist = parser.getUrls();
352  for (std::vector<Url>::iterator urliter = urllist.begin(); urliter != urllist.end(); ++urliter) {
353  try {
354  std::string scheme = urliter->getScheme();
355  if (scheme == "http" || scheme == "https" || scheme == "ftp" || scheme == "tftp") {
356  if ( !_requestDispatcher->supportsProtocol( *urliter ))
357  continue;
359  }
360  }
361  catch (...) { }
362  }
363 
364  if ( _multiPartMirrors.empty() )
365  _multiPartMirrors.push_back( _url );
366 
367  } catch ( const zypp::Exception &ex ) {
368  setFailed( zypp::str::Format("Failed to parse metalink information.(%1%)" ) % ex.asUserString() );
369  return;
370  }
371 
372  if ( _multiPartMirrors.size() == 0 ) {
373  setFailed( zypp::str::Format("Invalid metalink information.( No mirrors in metalink file)" ) );
374  return;
375  }
376 
377  if ( !_blockList.haveBlocks() ) {
378 
379  //if we have no filesize we can not generate a blocklist, we need to fall back to normal download
380  if ( !_blockList.haveFilesize() ) {
381  DBG << "No blocklist and no filesize, falling back to normal download for URL " << _url << std::endl;
382 
383  //fall back to normal download but use a mirror from the mirror list
384  //otherwise we get HTTPS to HTTP redirect errors
385  _isMultiDownload = false;
386  _isMultiPartEnabled = false;
387 
388  Url url;
389  TransferSettings set;
390  NetworkRequestError dummyErr;
391  if ( !findNextMirror( url, set, dummyErr ) ) {
392  url = _url;
393  set = _transferSettings;
394  }
395 
396  auto req = std::make_shared<Request>( internal::clearQueryString(url), _targetPath ) ;
397 
398  if ( _blockList.haveFileChecksum() ) {
399  std::shared_ptr<zypp::Digest> fileDigest = std::make_shared<zypp::Digest>();
400  if ( _blockList.createFileDigest( *fileDigest ) ) {
401  req->setDigest( fileDigest );
403  }
404  }
405 
406  req->transferSettings() = set;
407  addNewRequest( req );
408  return;
409 
410  } else {
411  //we generate a blocklist on the fly based on the filesize
412 
413  DBG << "Generate blocklist, since there was none in the metalink file." << _url << std::endl;
414 
415  off_t currOff = 0;
416  off_t filesize = _blockList.getFilesize();
417  while ( currOff < filesize ) {
418 
419  size_t blksize = static_cast<size_t>( filesize - currOff );
420  if ( blksize > BLKSIZE)
421  blksize = BLKSIZE;
422 
423  _blockList.addBlock( currOff, blksize );
424  currOff += blksize;
425  }
426 
427  XXX << "Generated blocklist: " << std::endl << _blockList << std::endl << " End blocklist " << std::endl;
428  }
429  }
430 
431  //remove the metalink file
433 
434  if ( !_deltaFilePath.empty() ) {
435  zypp::PathInfo dFileInfo ( _deltaFilePath );
436  if ( dFileInfo.isFile() && dFileInfo.isR() ) {
437  FILE *f = fopen( _targetPath.asString().c_str(), "w+b" );
438  if ( !f ) {
439  setFailed( zypp::str::Format("Failed to open target file.(errno %1%)" ) % errno );
440  return;
441  }
442 
443  try {
445  } catch ( ... ) { }
446 
447  fclose( f );
448  }
449  }
450 
452  _blockIter = 0;
453 
454  } else if ( _state == Download::RunningMulti ) {
456 
457  DBG << "Request finished " << reqLocked->_myBlock <<std::endl;
458 
459  auto restartReqWithBlock = [ this ]( std::shared_ptr<Request> &req, size_t block, int retryCount ) {
461  req->_myBlock = block;
462  req->_retryCount = retryCount;
463  req->setRequestRange( blk.off, static_cast<off_t>( blk.size ) );
464  req->setExpectedChecksum( _blockList.getChecksum( block ) );
465 
466  //this is not a new request, only add to queues but do not connect signals again
467  _runningRequests.push_back( req );
468  _requestDispatcher->enqueue( req );
469  };
470 
471  //check if we already have enqueued all blocks if not reuse the request
472  if ( _blockIter < _blockList.numBlocks() ) {
473 
474  DBG << "Reusing to download block: " << _blockIter <<std::endl;
475  restartReqWithBlock( reqLocked, _blockIter, 0 );
476  _blockIter++;
477  return;
478 
479  } else {
480  //if we have failed blocks, try to download them with this mirror
481  if ( !_failedBlocks.empty() ) {
482 
483  FailedBlock blk = std::move( _failedBlocks.front() );
484  _failedBlocks.pop_front();
485 
486  DBG << "Reusing to download failed block: " << blk._block <<std::endl;
487 
488  restartReqWithBlock( reqLocked, blk._block, blk._retryCount+1 );
489  return;
490  }
491 
492  //feed the working URL back into the mirrors in case there are still running requests that might fail
493  _multiPartMirrors.push_front( reqLocked->_originalUrl );
494  }
495  }
496 
497  //check if there is still work to do
498  if ( _runningRequests.size() < 10 ) {
499 
501 
502  //we try to allocate as many requests as possible but stop if we cannot find a valid mirror for one
503  for ( ; _blockIter < _blockList.numBlocks(); _blockIter++ ){
504 
505  if ( _runningRequests.size() >= 10 )
506  break;
507 
508  std::shared_ptr<Request> req = initMultiRequest( _blockIter, lastErr );
509  if ( !req )
510  break;
511 
512  addNewRequest( req );
513  }
514 
515  while ( _failedBlocks.size() ) {
516 
517  if ( _runningRequests.size() >= 10 )
518  break;
519 
520  FailedBlock blk = std::move( _failedBlocks.front() );
521  _failedBlocks.pop_front();
522 
523  auto req = initMultiRequest( blk._block, lastErr );
524  if ( !req )
525  break;
526 
527  addNewRequest( req );
528  }
529 
530  if ( _runningRequests.empty() && lastErr.type()!= NetworkRequestError::NoError ) {
531  //we found no mirrors -> fail
532  _requestError = lastErr;
533  setFailed( "Unable to use mirror" );
534  }
535  }
536 
537  if ( _runningRequests.empty() ) {
538 
539  if ( _failedBlocks.size() || ( _blockIter < _blockList.numBlocks() )) {
540  setFailed( "Unable to download all blocks." );
541  return;
542  }
543 
545  //TODO move this into a external application so we do not need to block on it
546  //need to check file digest
547  zypp::Digest dig;
549 
550  std::ifstream istrm( _targetPath.asString(), std::ios::binary);
551  if ( !istrm.is_open() ) {
552  setFailed( "Failed to verify file digest (Could not open target file)." );
553  return;
554  }
555  if ( !dig.update( istrm ) ) {
556  setFailed( "Failed to verify file digest (Could not read target file)." );
557  return;
558  }
559  if ( !_blockList.verifyFileDigest( dig ) ) {
560  setFailed( "Failed to verify file digest (Checksum did not match)." );
561  return;
562  }
563  }
564  //TODO implement digest check for non multi downloads
565  setFinished();
566  }
567  }
568 
569  void DownloadPrivate::addNewRequest( std::shared_ptr<Request> req )
570  {
571  auto slot = _sigStarted.slots().front();
572  req->connectSignals( *this );
573  _runningRequests.push_back( req );
574  _requestDispatcher->enqueue( req );
575  }
576 
577  std::shared_ptr<DownloadPrivate::Request> DownloadPrivate::initMultiRequest( size_t block, NetworkRequestError &err )
578  {
580 
581  Url myUrl;
582  TransferSettings settings;
583  if ( !findNextMirror( myUrl, settings, err ) )
584  return nullptr;
585 
586  DBG << "Starting block " << block << std::endl;
587 
588  std::shared_ptr<Request> req = std::make_shared<Request>( internal::clearQueryString( myUrl ), _targetPath, blk.off, blk.size, NetworkRequest::WriteShared );
589  req->_originalUrl = myUrl;
590  req->_myBlock = block;
591  req->setPriority( NetworkRequest::High );
592  req->transferSettings() = settings;
593 
594  if ( _blockList.haveChecksum( block ) ) {
595  std::shared_ptr<zypp::Digest> dig = std::make_shared<zypp::Digest>();
596  _blockList.createDigest( *dig );
597  req->setDigest( dig );
598  std::vector<unsigned char> checksumVec = _blockList.getChecksum( block );
599  req->setExpectedChecksum( checksumVec );
600  DBG << "Starting block " << block << " with checksum " << zypp::Digest::digestVectorToString( checksumVec ) << std::endl;
601  } else {
602  DBG << "Block " << block << " has no checksum." << std::endl;
603  }
604  return req;
605  }
606 
608  {
609  Url myUrl;
610  bool foundMirror = false;
611  TransferSettings settings;
612  while ( _multiPartMirrors.size() ) {
613  myUrl = _multiPartMirrors.front();
614  _multiPartMirrors.pop_front();
615 
616  settings = _transferSettings;
617  //if this is a different host than the initial request, we reset username/password
618  if ( myUrl.getHost() != _url.getHost() ) {
619  settings.setUsername( std::string() );
620  settings.setPassword( std::string() );
621  settings.setAuthType( std::string() );
622  }
623 
624  err = safeFillSettingsFromURL( myUrl, settings );
625  if ( err.type() != NetworkRequestError::NoError ) {
626  continue;
627  }
628 
629  foundMirror = true;
630  break;
631  }
632 
633  if ( !foundMirror )
634  return false;
635 
636  url = myUrl;
637  set = settings;
638  return true;
639  }
640 
641  void DownloadPrivate::setFailed(std::string &&reason)
642  {
643  _errorString = reason;
644  //zypp::filesystem::unlink( _targetPath );
645  setFinished( false );
646  }
647 
648  void DownloadPrivate::setFinished(bool success)
649  {
651  _sigFinished.emit( *z_func() );
652  }
653 
655  {
656  auto buildExtraInfo = [this, &url](){
657  std::map<std::string, boost::any> extraInfo;
658  extraInfo.insert( {"requestUrl", url } );
659  extraInfo.insert( {"filepath", _targetPath } );
660  return extraInfo;
661  };
662 
664  try {
666  if ( _transferSettings.proxy().empty() )
668  } catch ( const zypp::media::MediaBadUrlException & e ) {
670  } catch ( const zypp::media::MediaUnauthorizedException & e ) {
672  } catch ( const zypp::Exception & e ) {
674  }
675  return res;
676  }
677 
679  : Base( prv )
680  { }
681 
683  {
684  return d_func()->_url;
685  }
686 
688  {
689  return d_func()->_targetPath;
690  }
691 
693  {
694  return d_func()->_state;
695  }
696 
698  {
699  return d_func()->_requestError;
700  }
701 
702  std::string Download::errorString() const
703  {
704  Z_D();
705  if (! d->_requestError.isError() ) {
706  return d->_errorString;
707  }
708 
709  return ( zypp::str::Format("%1%(%2% %3%)") % d->_errorString % d->_requestError.toString() % d->_requestError.nativeErrorString() );
710  }
711 
713  {
714  return d_func()->_transferSettings;
715  }
716 
718  {
719  d_func()->start();
720  }
721 
723  {
724  d_func()->_isMultiPartEnabled = enable;
725  }
726 
728  {
729  Z_D();
730  if ( d->_checkExistsOnly != set ) {
731  d_func()->_checkExistsOnly = set;
732  if ( set == true )
733  d_func()->_isMultiPartEnabled = false;
734  }
735  }
736 
738  {
739  d_func()->_deltaFilePath = file;
740  }
741 
742  zyppng::NetworkRequestDispatcher &Download::dispatcher() const
743  {
744  return *d_func()->_requestDispatcher;
745  }
746 
748  {
749  return d_func()->_sigStarted;
750  }
751 
753  {
754  return d_func()->_sigStateChanged;
755  }
756 
758  {
759  return d_func()->_sigAlive;
760  }
761 
763  {
764  return d_func()->_sigProgress;
765  }
766 
768  {
769  return d_func()->_sigFinished;
770  }
771 
773  {
774  return d_func()->_sigAuthRequired;
775  }
776 
778  {
779  _requestDispatcher = std::make_shared<NetworkRequestDispatcher>( );
780  }
781 
783  {
784  _sigStarted.emit( *z_func(), download );
785  }
786 
788  {
789  _sigFinished.emit( *z_func(), download );
790 
791  auto it = std::find_if( _runningDownloads.begin(), _runningDownloads.end(), [ &download ]( const std::shared_ptr<Download> &dl){
792  return dl.get() == &download;
793  });
794 
795  if ( it != _runningDownloads.end() ) {
796  //make sure this is not deleted before all user code was done
798  _runningDownloads.erase( it );
799  }
800 
801  if ( _runningDownloads.empty() )
802  _queueEmpty.emit( *z_func() );
803  }
804 
806  : Base ( *new DownloaderPrivate( ) )
807  {
808 
809  }
810 
811  std::shared_ptr<Download> Downloader::downloadFile(zyppng::Url file, zypp::filesystem::Pathname targetPath, zypp::ByteCount expectedFileSize )
812  {
813  Z_D();
814  std::shared_ptr<Download> dl = std::make_shared<Download>( std::move( *new DownloadPrivate( *this, d->_requestDispatcher, std::move(file), std::move(targetPath), std::move(expectedFileSize) ) ) );
815 
816  d->_runningDownloads.push_back( dl );
817  dl->sigFinished().connect( sigc::mem_fun( *d , &DownloaderPrivate::onDownloadFinished ) );
818 
819  d->_requestDispatcher->run();
820 
821  return dl;
822  }
823 
824  std::shared_ptr<NetworkRequestDispatcher> Downloader::requestDispatcher() const
825  {
826  return d_func()->_requestDispatcher;
827  }
828 
830  {
831  return d_func()->_sigStarted;
832  }
833 
835  {
836  return d_func()->_sigFinished;
837  }
838 
840  {
841  return d_func()->_queueEmpty;
842  }
843 
844 }
size_t addBlock(off_t off, size_t size)
add a block with offset off and size size to the block list.
void setFinished(bool success=true)
Definition: downloader.cc:648
bool isError() const
isError Will return true if this is a actual error
static void unrefLater(T &&ptr)
TransferSettings & settings()
Definition: downloader.cc:712
std::string password() const
Definition: MediaUserAuth.h:57
SignalProxy< void(Download &req, off_t dlnow)> sigAlive()
Definition: downloader.cc:757
The Downloader class.
Definition: downloader.h:34
void addHeader(std::string &&val_r)
add a header, on the form "Foo: Bar"
void onRequestStarted(NetworkRequest &)
Definition: downloader.cc:132
Unit::ValueType SizeType
Definition: ByteCount.h:37
std::deque< Url > _multiPartMirrors
Definition: downloader_p.h:66
void setAuthType(std::string &&val_r)
set the allowed authentication types
signal< void(Downloader &parent, Download &download)> _sigFinished
Definition: downloader_p.h:111
std::shared_ptr< Request > initMultiRequest(size_t block, NetworkRequestError &err)
Definition: downloader.cc:577
Url url() const
Definition: downloader.cc:682
static ZConfig & instance()
Singleton ctor.
Definition: Resolver.cc:124
zypp::Url propagateQueryParams(zypp::Url url_r, const zypp::Url &template_r)
Definition: CurlHelper.cc:375
Compute Message Digests (MD5, SHA1 etc)
Definition: Digest.h:45
Download::State _state
Definition: downloader_p.h:71
void setAuthType(std::string auth_type)
Set HTTP authentication type(s) to use.
void setUsername(std::string &&val_r)
sets the auth username
Store and operate with byte count.
Definition: ByteCount.h:30
std::string proxy() const
proxy host
Holds transfer setting.
void reuseBlocks(FILE *wfp, std::string filename)
scan a file for blocks from our blocklist.
void save()
Saves any unsaved credentials added via addUserCred() or addGlobalCred() methods. ...
SignalProxy< void(Download &req, NetworkAuthData &auth, const std::string &availAuth)> sigAuthRequired()
Definition: downloader.cc:772
std::shared_ptr< NetworkRequestDispatcher > _requestDispatcher
Definition: downloader_p.h:105
Url clearQueryString(const Url &url)
Definition: CurlHelper.cc:349
static std::string digestVectorToString(const std::vector< unsigned char > &vec)
get hex string representation of the digest vector given as parameter
Definition: Digest.cc:193
bool createDigest(Digest &digest) const
const char * c_str() const
String representation.
Definition: Pathname.h:110
std::vector< std::shared_ptr< Request > > _runningRequests
Definition: downloader_p.h:52
zypp::media::MediaBlockList _blockList
Definition: downloader_p.h:67
Definition: Arch.h:347
AuthData_Ptr getCred(const Url &url)
Get credentials for the specified url.
Url url
Definition: MediaCurl.cc:65
#define XXX
Definition: Logger.h:77
static const Unit MB
1000^2 Byte
Definition: ByteCount.h:60
std::vector< std::shared_ptr< Download > > _runningDownloads
Definition: downloader_p.h:104
Convenient building of std::string with boost::format.
Definition: String.h:249
std::string authTypeAsString() const
SignalProxy< void(Downloader &parent, Download &download)> sigStarted()
Definition: downloader.cc:829
TransferSettings & transferSettings()
Definition: request.cc:607
SignalProxy< void(Download &req)> sigFinished()
Definition: downloader.cc:767
void setFailed(std::string &&reason)
Definition: downloader.cc:641
void parse(const Pathname &filename)
parse a file consisting of metalink xml data
DownloadPrivate(Downloader &parent, std::shared_ptr< NetworkRequestDispatcher > requestDispatcher, Url &&file, zypp::filesystem::Pathname &&targetPath, zypp::ByteCount &&expectedFileSize)
Definition: downloader.cc:60
signal< void(Downloader &parent)> _queueEmpty
Definition: downloader_p.h:112
#define Z_D()
Definition: zyppglobal.h:44
signal< void(Download &req, Download::State state)> _sigStateChanged
Definition: downloader_p.h:78
void onDownloadFinished(Download &download)
Definition: downloader.cc:787
SignalProxy< void(Downloader &parent, Download &download)> sigFinished()
Definition: downloader.cc:834
bool haveBlocks() const
do we have a blocklist describing the file? set to true when addBlock() is called ...
void setUrl(const Url &url)
Definition: MediaUserAuth.h:51
bool empty() const
Test for an empty path.
Definition: Pathname.h:114
std::shared_ptr< NetworkRequestDispatcher > _requestDispatcher
Definition: downloader_p.h:53
const std::map< std::string, boost::any > & extraInfo() const
std::string _errorString
Definition: downloader_p.h:59
zypp::Pathname _deltaFilePath
Definition: downloader_p.h:57
State state() const
Definition: downloader.cc:692
void setDigest(std::shared_ptr< zypp::Digest > dig)
Set a.
Definition: request.cc:597
bool verifyFileDigest(Digest &digest) const
void connectSignals(DownloadPrivate &dl)
Definition: downloader.cc:68
void setCheckExistsOnly(bool set=true)
Definition: downloader.cc:727
int unlink(const Pathname &path)
Like &#39;unlink&#39;.
Definition: PathInfo.cc:653
TransferSettings _transferSettings
Definition: downloader_p.h:62
const std::string & asString() const
String representation.
Definition: Pathname.h:91
zypp::Pathname targetPath() const
Definition: downloader.cc:687
std::string asString() const
Error message provided by dumpOn as string.
Definition: Exception.cc:75
#define BLKSIZE
Definition: downloader.cc:24
std::string asUserString() const
Translated error message as string suitable for the user.
Definition: Exception.cc:82
#define WAR
Definition: Logger.h:80
The NetworkRequestError class Represents a error that occured in.
std::shared_ptr< NetworkRequestDispatcher > requestDispatcher() const
Definition: downloader.cc:824
std::vector< char > peekData(off_t offset, size_t count) const
Definition: request.cc:541
std::string username() const
Definition: MediaUserAuth.h:56
zypp::media::CurlAuthData_Ptr NetworkAuthData_Ptr
Definition: authdata.h:25
a single block from the blocklist, consisting of an offset and a size
bool createFileDigest(Digest &digest) const
void fillSettingsFromUrl(const Url &url, media::TransferSettings &s)
Fills the settings structure using options passed on the url for example ?timeout=x&proxy=foo.
Definition: CurlHelper.cc:101
void setDeltaFile(const zypp::Pathname &file)
Definition: downloader.cc:737
signal< void(Download &req, off_t dlnow)> _sigAlive
Definition: downloader_p.h:79
NetworkRequestDispatcher & dispatcher() const
Definition: downloader.cc:742
Download(DownloadPrivate &&prv)
Definition: downloader.cc:678
signal< void(Download &req, off_t dltotal, off_t dlnow)> _sigProgress
Definition: downloader_p.h:80
size_t numBlocks() const
return the number of blocks in the blocklist
bool findNextMirror(Url &url, TransferSettings &set, NetworkRequestError &err)
Definition: downloader.cc:607
std::shared_ptr< Download > downloadFile(Url file, zypp::filesystem::Pathname targetPath, zypp::ByteCount expectedFileSize=zypp::ByteCount())
Definition: downloader.cc:811
NetworkRequestError safeFillSettingsFromURL(const Url &url, TransferSettings &set)
Definition: downloader.cc:654
MediaBlockList getBlockList()
return the block list from the parsed metalink data
const zypp::Pathname & targetFilePath() const
Returns the target filename path.
Definition: request.cc:561
void onRequestFinished(NetworkRequest &req, const NetworkRequestError &err)
Definition: downloader.cc:192
signal< void(zyppng::Download &req, zyppng::NetworkAuthData &auth, const std::string &availAuth)> _sigAuthRequired
Definition: downloader_p.h:82
NetworkRequestError lastRequestError() const
Definition: downloader.cc:697
signal< void(Downloader &parent, Download &download)> _sigStarted
Definition: downloader_p.h:110
std::vector< char > peek_data_fd(FILE *fd, off_t offset, size_t count)
Definition: request.cc:18
void setState(Download::State newState)
Definition: downloader.cc:124
zypp::media::CurlAuthData NetworkAuthData
Definition: authdata.h:24
SignalProxy< void(Downloader &parent)> queueEmpty()
Definition: downloader.cc:839
std::string contentType() const
Returns the content type as reported from the server.
Definition: request.cc:566
signal< void(Download &req)> _sigStarted
Definition: downloader_p.h:77
SignalProxy< void(Download &req)> sigStarted()
Definition: downloader.cc:747
Base class for Exception.
Definition: Exception.h:145
std::vector< Url > getUrls()
return the download urls from the parsed metalink data
void onDownloadStarted(Download &download)
Definition: downloader.cc:782
std::deque< FailedBlock > _failedBlocks
Definition: downloader_p.h:50
std::string getHost(EEncoding eflag=zypp::url::E_DECODED) const
Returns the hostname or IP from the URL authority.
Definition: Url.cc:583
bool haveChecksum(size_t blkno) const
void setMultiPartHandlingEnabled(bool enable=true)
Definition: downloader.cc:722
SignalProxy< void(Download &req, off_t dltotal, off_t dlnow)> sigProgress()
Definition: downloader.cc:762
NetworkRequestError _requestError
Definition: downloader_p.h:60
Wrapper class for ::stat/::lstat.
Definition: PathInfo.h:220
zypp::ByteCount _expectedFileSize
Definition: downloader_p.h:58
SignalProxy< void(NetworkRequest &req, const NetworkRequestError &err)> sigFinished()
Signals that the download finished.
Definition: request.cc:665
const std::vector< unsigned char > & getFileChecksum()
void fillSettingsSystemProxy(const Url &url, media::TransferSettings &s)
Reads the system proxy configuration and fills the settings structure proxy information.
Definition: CurlHelper.cc:249
signal< void(Download &req)> _sigFinished
Definition: downloader_p.h:81
Type type() const
type Returns the type of the error
SignalProxy< void(NetworkRequest &req)> sigStarted()
Signals that the dispatcher dequeued the request and actually starts downloading data.
Definition: request.cc:655
void setExpectedChecksum(std::vector< unsigned char > checksum)
Enables automated checking of downloaded contents against a checksum.
Definition: request.cc:602
void setPassword(std::string &&val_r)
sets the auth password
void setUsername(const std::string &username)
Definition: MediaUserAuth.h:52
zypp::filesystem::Pathname _targetPath
Definition: downloader_p.h:56
void addCred(const AuthData &cred)
Add new credentials with user callbacks.
std::vector< unsigned char > getChecksum(size_t blkno)
Curl HTTP authentication data.
Definition: MediaUserAuth.h:74
std::string errorString() const
Definition: downloader.cc:702
off_t downloadedByteCount() const
Returns the number of already downloaded bytes as reported by the backend.
Definition: request.cc:589
SignalProxy< void(Download &req, State state)> sigStateChanged()
Definition: downloader.cc:752
bool update(const char *bytes, size_t len)
feed data into digest computation algorithm
Definition: Digest.cc:225
static zyppng::NetworkRequestError customError(NetworkRequestError::Type t, std::string &&errorMsg="", std::map< std::string, boost::any > &&extraInfo={})
SignalProxy< void(NetworkRequest &req, off_t dltotal, off_t dlnow, off_t ultotal, off_t ulnow)> sigProgress()
Signals if there was data read from the download.
Definition: request.cc:660
virtual bool valid() const
Checks validity of authentication data.
void addNewRequest(std::shared_ptr< Request > req)
Definition: downloader.cc:569
Url manipulation class.
Definition: Url.h:87
#define DBG
Definition: Logger.h:78
MediaBlock getBlock(size_t blkno) const
return the offset/size of a block with number blkno
void onRequestProgress(NetworkRequest &req, off_t dltotal, off_t dlnow, off_t, off_t)
Definition: downloader.cc:138
ByteCount _expectedFileSize
Definition: MediaCurl.cc:70