libzypp: zypp-curl/ng/network/request.cc Source File

libzypp 17.38.6

request.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8----------------------------------------------------------------------*/
9#include <zypp-curl/ng/network/private/request_p.h>
10#include <zypp-curl/ng/network/private/networkrequesterror_p.h>
11#include <zypp-curl/ng/network/networkrequestdispatcher.h>
12#include <zypp-curl/ng/network/private/mediadebug_p.h>
13#include <zypp-core/ng/base/EventDispatcher>
14#include <zypp-core/ng/base/private/linuxhelpers_p.h>
15#include <zypp-core/ng/core/String>
16#include <zypp-core/fs/PathInfo.h>
17#include <zypp-curl/private/curlhelper_p.h>
18#include <zypp-curl/CurlConfig>
19#include <zypp-curl/auth/CurlAuthData>
20#include <zypp-media/MediaConfig>
21#include <zypp-core/base/String.h>
22#include <zypp-core/base/StringV.h>
23#include <zypp-core/base/IOTools.h>
24#include <zypp-core/Pathname.h>
25#include <curl/curl.h>
26#include <stdio.h>
27#include <fcntl.h>
28#include <utility>
29
30#include <iostream>
31#include <boost/variant.hpp>
32#include <boost/variant/polymorphic_get.hpp>
33
34
35namespace zyppng {
36
37 namespace {
38 static size_t nwr_headerCallback ( char *ptr, size_t size, size_t nmemb, void *userdata ) {
39 if ( !userdata )
40 return 0;
41
42 NetworkRequestPrivate *that = reinterpret_cast<NetworkRequestPrivate *>( userdata );
43 return that->headerfunction( ptr, size * nmemb );
44 }
45 static size_t nwr_writeCallback ( char *ptr, size_t size, size_t nmemb, void *userdata ) {
46 if ( !userdata )
47 return 0;
48
49 NetworkRequestPrivate *that = reinterpret_cast<NetworkRequestPrivate *>( userdata );
50 return that->writefunction( ptr, {}, size * nmemb );
51 }
52
53 //helper for std::visit
54 template<class T> struct always_false : std::false_type {};
55 }
56
57 NetworkRequestPrivate::prepareNextRangeBatch_t::prepareNextRangeBatch_t(running_t &&prevState)
58 : _outFile( std::move(prevState._outFile) )
59 , _downloaded( prevState._downloaded )
60 , _partialHelper( std::move(prevState._partialHelper) )
61 { }
62
63 NetworkRequestPrivate::running_t::running_t( pending_t &&prevState )
64 : _partialHelper( std::move(prevState._partialHelper) )
65 { }
66
67 NetworkRequestPrivate::running_t::running_t( prepareNextRangeBatch_t &&prevState )
68 : _outFile( std::move(prevState._outFile) )
69 , _partialHelper( std::move(prevState._partialHelper) )
70 , _downloaded( prevState._downloaded )
71 { }
72
73 NetworkRequestPrivate::NetworkRequestPrivate(Url &&url, zypp::Pathname &&targetFile, NetworkRequest::FileMode fMode , NetworkRequest &p)
74 : BasePrivate(p)
75 , _url ( std::move(url) )
76 , _targetFile ( std::move( targetFile) )
77 , _fMode ( std::move(fMode) )
78 , _headers( std::unique_ptr< curl_slist, decltype (&curl_slist_free_all) >( nullptr, &curl_slist_free_all ) )
79 { }
80
81 NetworkRequestPrivate::~NetworkRequestPrivate()
82 {
83 if ( _easyHandle ) {
84 //clean up for now, later we might reuse handles
85 curl_easy_cleanup( _easyHandle );
86 MIL << _easyHandle << " curl_easy_cleanup" << std::endl;
87 //reset in request but make sure the request was not enqueued again and got a new handle
88 _easyHandle = nullptr;
89 }
90 }
91
92 bool NetworkRequestPrivate::initialize( std::string &errBuf )
93 {
94 reset();
95
96 if ( _easyHandle ) {
97 //will reset to defaults but keep live connections, session ID and DNS caches
98 curl_easy_reset( _easyHandle );
99 MIL << _easyHandle << " curl_easy_reset" << std::endl;
100 } else
101 _easyHandle = curl_easy_init();
102 return setupHandle ( errBuf );
103 }
104
105 bool NetworkRequestPrivate::setupHandle( std::string &errBuf )
106 {
107 ::internal::setupZYPP_MEDIA_CURL_DEBUG( _easyHandle );
108 curl_easy_setopt( _easyHandle, CURLOPT_ERRORBUFFER, this->_errorBuf.data() );
109 MIL << _easyHandle << " " << "URL: " << _url << std::endl;
110
111 const std::string urlScheme = _url.getScheme();
112 if ( urlScheme == "http" || urlScheme == "https" )
113 _protocolMode = ProtocolMode::HTTP;
114
115 try {
116
117 setCurlOption( CURLOPT_PRIVATE, this );
118 setCurlOption( CURLOPT_XFERINFOFUNCTION, NetworkRequestPrivate::curlProgressCallback );
119 setCurlOption( CURLOPT_XFERINFODATA, this );
120 setCurlOption( CURLOPT_NOPROGRESS, 0L);
121 setCurlOption( CURLOPT_FAILONERROR, 1L);
122 setCurlOption( CURLOPT_NOSIGNAL, 1L);
123
124 std::string urlBuffer( _url.asString() );
125 setCurlOption( CURLOPT_URL, urlBuffer.c_str() );
126
127 setCurlOption( CURLOPT_WRITEFUNCTION, nwr_writeCallback );
128 setCurlOption( CURLOPT_WRITEDATA, this );
129
130 if ( _options & NetworkRequest::ConnectionTest ) {
131 setCurlOption( CURLOPT_CONNECT_ONLY, 1L );
132 setCurlOption( CURLOPT_FRESH_CONNECT, 1L );
133 }
134 if ( _options & NetworkRequest::HeadRequest ) {
135 // instead of returning no data with NOBODY, we return
136 // little data, that works with broken servers, and
137 // works for ftp as well, because retrieving only headers
138 // ftp will return always OK code ?
139 // See http://curl.haxx.se/docs/knownbugs.html #58
140 if ( _protocolMode == ProtocolMode::HTTP && _settings.headRequestsAllowed() )
141 setCurlOption( CURLOPT_NOBODY, 1L );
142 else
143 setCurlOption( CURLOPT_RANGE, "0-1" );
144 }
145
146 //make a local copy of the settings, so headers are not added multiple times
147 TransferSettings locSet = _settings;
148
149 if ( _dispatcher ) {
150 locSet.setUserAgentString( _dispatcher->agentString().c_str() );
151
152 // add custom headers as configured (bsc#955801)
153 const auto &cHeaders = _dispatcher->hostSpecificHeaders();
154 if ( auto i = cHeaders.find(_url.getHost()); i != cHeaders.end() ) {
155 for ( const auto &[key, value] : i->second ) {
156 locSet.addHeader( zypp::str::trim( zypp::str::form(
157 "%s: %s", key.c_str(), value.c_str() )
158 ));
159 }
160 }
161 }
162
163 locSet.addHeader("Pragma:");
164
166 switch ( zypp::env::ZYPP_MEDIA_CURL_IPRESOLVE() )
167 {
168 case 4: setCurlOption( CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4 ); break;
169 case 6: setCurlOption( CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6 ); break;
170 default: break;
171 }
172
173 setCurlOption( CURLOPT_HEADERFUNCTION, &nwr_headerCallback );
174 setCurlOption( CURLOPT_HEADERDATA, this );
175
179 setCurlOption( CURLOPT_CONNECTTIMEOUT, locSet.connectTimeout() );
180 // If a transfer timeout is set, also set CURLOPT_TIMEOUT to an upper limit
181 // just in case curl does not trigger its progress callback frequently
182 // enough.
183 if ( locSet.timeout() )
184 {
185 setCurlOption( CURLOPT_TIMEOUT, 3600L );
186 }
187
188 if ( urlScheme == "https" )
189 {
190 if ( :: internal::setCurlRedirProtocols ( _easyHandle ) != CURLE_OK ) {
191 ZYPP_THROW( zypp::media::MediaCurlSetOptException( _url, _errorBuf.data() ) );
192 }
193
194 if( locSet.verifyPeerEnabled() ||
195 locSet.verifyHostEnabled() )
196 {
197 setCurlOption(CURLOPT_CAPATH, locSet.certificateAuthoritiesPath().c_str());
198 }
199
200 if( ! locSet.clientCertificatePath().empty() )
201 {
202 setCurlOption(CURLOPT_SSLCERT, locSet.clientCertificatePath().c_str());
203 }
204 if( ! locSet.clientKeyPath().empty() )
205 {
206 setCurlOption(CURLOPT_SSLKEY, locSet.clientKeyPath().c_str());
207 }
208
209#ifdef CURLSSLOPT_ALLOW_BEAST
210 // see bnc#779177
211 setCurlOption( CURLOPT_SSL_OPTIONS, CURLSSLOPT_ALLOW_BEAST );
212#endif
213 setCurlOption(CURLOPT_SSL_VERIFYPEER, locSet.verifyPeerEnabled() ? 1L : 0L);
214 setCurlOption(CURLOPT_SSL_VERIFYHOST, locSet.verifyHostEnabled() ? 2L : 0L);
215 // bnc#903405 - POODLE: libzypp should only talk TLS
216 setCurlOption(CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
217 }
218
219 // follow any Location: header that the server sends as part of
220 // an HTTP header (#113275)
221 setCurlOption( CURLOPT_FOLLOWLOCATION, 1L);
222 // 3 redirects seem to be too few in some cases (bnc #465532)
223 setCurlOption( CURLOPT_MAXREDIRS, 6L );
224
225 //set the user agent
226 setCurlOption(CURLOPT_USERAGENT, locSet.userAgentString().c_str() );
227
228
229 /*---------------------------------------------------------------*
230 CURLOPT_USERPWD: [user name]:[password]
231 Url::username/password -> CURLOPT_USERPWD
232 If not provided, anonymous FTP identification
233 *---------------------------------------------------------------*/
234 if ( locSet.hasCredentials() )
235 {
236 locSet.logCredentials( DBG << "Credentials: " ) << std::endl;
237 setCurlOption(CURLOPT_USERNAME, locSet.username().c_str());
238 setCurlOption(CURLOPT_PASSWORD, locSet.password().c_str());
239 std::string use_auth = _settings.authType();
240 if (use_auth.empty())
241 use_auth = "digest,basic"; // our default
242 long auth = zypp::media::CurlAuthData::auth_type_str2long(use_auth);
243 if( auth != CURLAUTH_NONE)
244 {
245 DBG << _easyHandle << " " << "Enabling HTTP authentication methods: " << use_auth
246 << " (CURLOPT_HTTPAUTH=" << auth << ")" << std::endl;
247 setCurlOption(CURLOPT_HTTPAUTH, auth);
248 }
249 }
250
251 if ( locSet.proxyEnabled() && ! locSet.proxy().empty() )
252 {
253 DBG << _easyHandle << " " << "Proxy: '" << locSet.proxy() << "'" << std::endl;
254 setCurlOption(CURLOPT_PROXY, locSet.proxy().c_str());
255 setCurlOption(CURLOPT_PROXYAUTH, CURLAUTH_BASIC|CURLAUTH_DIGEST|CURLAUTH_NTLM );
256
257 /*---------------------------------------------------------------*
258 * CURLOPT_PROXYUSERPWD: [user name]:[password]
259 *
260 * Url::option(proxyuser and proxypassword) -> CURLOPT_PROXYUSERPWD
261 * If not provided, $HOME/.curlrc is evaluated
262 *---------------------------------------------------------------*/
263
264 std::string proxyuserpwd = locSet.proxyUserPassword();
265
266 if ( proxyuserpwd.empty() )
267 {
268 zypp::media::CurlConfig curlconf;
269 zypp::media::CurlConfig::parseConfig(curlconf); // parse ~/.curlrc
270 if ( curlconf.proxyuserpwd.empty() )
271 DBG << _easyHandle << " " << "Proxy: ~/.curlrc does not contain the proxy-user option" << std::endl;
272 else
273 {
274 proxyuserpwd = curlconf.proxyuserpwd;
275 DBG << _easyHandle << " " << "Proxy: using proxy-user from ~/.curlrc" << std::endl;
276 }
277 }
278 else
279 {
280 DBG << _easyHandle << " " << "Proxy: using provided proxy-user '" << _settings.proxyUsername() << "'" << std::endl;
281 }
282
283 if ( ! proxyuserpwd.empty() )
284 {
285 setCurlOption(CURLOPT_PROXYUSERPWD, ::internal::curlUnEscape( proxyuserpwd ).c_str());
286 }
287 }
288#if CURLVERSION_AT_LEAST(7,19,4)
289 else if ( locSet.proxy() == EXPLICITLY_NO_PROXY )
290 {
291 // Explicitly disabled in URL (see fillSettingsFromUrl()).
292 // This should also prevent libcurl from looking into the environment.
293 DBG << _easyHandle << " " << "Proxy: explicitly NOPROXY" << std::endl;
294 setCurlOption(CURLOPT_NOPROXY, "*");
295 }
296
297#endif
298 // else: Proxy: not explicitly set; libcurl may look into the environment
299
301 if ( locSet.minDownloadSpeed() != 0 )
302 {
303 setCurlOption(CURLOPT_LOW_SPEED_LIMIT, locSet.minDownloadSpeed());
304 // default to 10 seconds at low speed
305 setCurlOption(CURLOPT_LOW_SPEED_TIME, 60L);
306 }
307
308#if CURLVERSION_AT_LEAST(7,15,5)
309 if ( locSet.maxDownloadSpeed() != 0 )
310 setCurlOption(CURLOPT_MAX_RECV_SPEED_LARGE, locSet.maxDownloadSpeed());
311#endif
312
313 if ( locSet.cookieFileEnabled() ) {
314 DBG << _easyHandle << " " << "Cookie file enabled: " << _currentCookieFile << std::endl;
315 zypp::filesystem::assert_file_mode( _currentCookieFile, 0600 );
316 setCurlOption( CURLOPT_COOKIEFILE, _currentCookieFile.c_str() );
317 setCurlOption(CURLOPT_COOKIEJAR, _currentCookieFile.c_str() );
318 }
319
320#if CURLVERSION_AT_LEAST(7,18,0)
321 // bnc #306272
322 setCurlOption(CURLOPT_PROXY_TRANSFER_MODE, 1L );
323#endif
324
325 // Append settings custom headers to curl.
326 // TransferSettings assert strings are trimmed (HTTP/2 RFC 9113)
327 for ( const auto &header : locSet.headers() ) {
328 if ( !z_func()->addRequestHeader( header.c_str() ) )
329 ZYPP_THROW(zypp::media::MediaCurlInitException(_url));
330 }
331
332 if ( _headers )
333 setCurlOption( CURLOPT_HTTPHEADER, _headers.get() );
334
335 // set up ranges if required
336 if( !( _options & NetworkRequest::ConnectionTest ) && !( _options & NetworkRequest::HeadRequest ) ){
337 if ( _requestedRanges.size() ) {
338
339 std::sort( _requestedRanges.begin(), _requestedRanges.end(), []( const auto &elem1, const auto &elem2 ){
340 return ( elem1._start < elem2._start );
341 });
342
343 CurlMultiPartHandler *helper = nullptr;
344 if ( auto initState = std::get_if<pending_t>(&_runningMode) ) {
345
346 auto multiPartMode = _protocolMode == ProtocolMode::HTTP ? CurlMultiPartHandler::ProtocolMode::HTTP : CurlMultiPartHandler::ProtocolMode::Basic;
347 initState->_partialHelper = std::make_unique<CurlMultiPartHandler>(
348 multiPartMode
349 , _easyHandle
350 , _requestedRanges
351 , *this
352 );
353 helper = initState->_partialHelper.get();
354
355 } else if ( auto pendingState = std::get_if<prepareNextRangeBatch_t>(&_runningMode) ) {
356 helper = pendingState->_partialHelper.get();
357 } else {
358 errBuf = "Request is in invalid state to call setupHandle";
359 return false;
360 }
361
362 if ( !helper->prepare () ) {
363 errBuf = helper->lastErrorMessage ();
364 return false;
365 }
366 }
367 }
368
369 return true;
370
371 } catch ( const zypp::Exception &excp ) {
372 ZYPP_CAUGHT(excp);
373 errBuf = excp.asString();
374 }
375 return false;
376 }
377
378 bool NetworkRequestPrivate::assertOutputFile()
379 {
380 auto rmode = std::get_if<NetworkRequestPrivate::running_t>( &_runningMode );
381 if ( !rmode ) {
382 DBG << _easyHandle << "Can only create output file in running mode" << std::endl;
383 return false;
384 }
385 // if we have no open file create or open it
386 if ( !rmode->_outFile ) {
387 std::string openMode = "w+b";
388 if ( _fMode == NetworkRequest::WriteShared )
389 openMode = "r+b";
390
391 rmode->_outFile = fopen( _targetFile.asString().c_str() , openMode.c_str() );
392
393 //if the file does not exist create a new one
394 if ( !rmode->_outFile && _fMode == NetworkRequest::WriteShared ) {
395 rmode->_outFile = fopen( _targetFile.asString().c_str() , "w+b" );
396 }
397
398 if ( !rmode->_outFile ) {
399 rmode->_cachedResult = NetworkRequestErrorPrivate::customError( NetworkRequestError::InternalError
400 ,zypp::str::Format("Unable to open target file (%1%). Errno: (%2%:%3%)") % _targetFile.asString() % errno % strerr_cxx() );
401 return false;
402 }
403 }
404
405 return true;
406 }
407
408 bool NetworkRequestPrivate::canRecover() const
409 {
410 // We can recover from RangeFail errors if the helper indicates it
411 auto rmode = std::get_if<NetworkRequestPrivate::running_t>( &_runningMode );
412 if ( rmode->_partialHelper ) return rmode->_partialHelper->canRecover();
413 return false;
414 }
415
416 bool NetworkRequestPrivate::prepareToContinue( std::string &errBuf )
417 {
418 auto rmode = std::get_if<NetworkRequestPrivate::running_t>( &_runningMode );
419 if ( !rmode ) {
420 errBuf = "NetworkRequestPrivate::prepareToContinue called in invalid state";
421 return false;
422 }
423
424 if ( rmode->_partialHelper && rmode->_partialHelper->hasMoreWork() ) {
425
426 bool hadRangeFail = rmode->_partialHelper->lastError () == NetworkRequestError::RangeFail;
427
428 _runningMode = prepareNextRangeBatch_t( std::move(std::get<running_t>( _runningMode )) );
429
430 auto &prepMode = std::get<prepareNextRangeBatch_t>(_runningMode);
431 if ( !prepMode._partialHelper->prepareToContinue() ) {
432 errBuf = prepMode._partialHelper->lastErrorMessage();
433 return false;
434 }
435
436 if ( hadRangeFail ) {
437 // we reset the handle to default values. We do this to not run into
438 // "transfer closed with outstanding read data remaining" error CURL sometimes returns when
439 // we cancel a connection because of a range error to request a smaller batch.
440 // The error will still happen but much less frequently than without resetting the handle.
441 //
442 // Note: Even creating a new handle will NOT fix the issue
443 curl_easy_reset( _easyHandle );
444 MIL << _easyHandle << " curl_easy_reset after hadRangeFail" << std::endl;
445 }
446 if ( !setupHandle(errBuf))
447 return false;
448
449 return true;
450 }
451 errBuf = "Request has no more work";
452 return false;
453
454 }
455
456 bool NetworkRequestPrivate::hasMoreWork() const
457 {
458 // check if we have ranges that have never been requested
459 return std::any_of( _requestedRanges.begin(), _requestedRanges.end(), []( const auto &range ){ return range._rangeState == CurlMultiPartHandler::Pending; });
460 }
461
462 void NetworkRequestPrivate::aboutToStart( )
463 {
464 bool isRangeContinuation = std::holds_alternative<prepareNextRangeBatch_t>( _runningMode );
465 if ( isRangeContinuation ) {
466 MIL << _easyHandle << " " << "Continuing a previously started range batch." << std::endl;
467 _runningMode = running_t( std::move(std::get<prepareNextRangeBatch_t>( _runningMode )) );
468 } else {
469 _runningMode = running_t( std::move(std::get<pending_t>( _runningMode )) );
470 }
471
472 auto &m = std::get<running_t>( _runningMode );
473
474 if ( m._activityTimer ) {
475 DBG_MEDIA << _easyHandle << " Setting activity timeout to: " << _settings.timeout() << std::endl;
476 m._activityTimer->connect( &Timer::sigExpired, *this, &NetworkRequestPrivate::onActivityTimeout );
477 m._activityTimer->start( static_cast<uint64_t>( _settings.timeout() * 1000 ) );
478 }
479
480 if ( !isRangeContinuation )
481 _sigStarted.emit( *z_func() );
482 }
483
484 void NetworkRequestPrivate::dequeueNotify()
485 {
486 if ( std::holds_alternative<running_t>(_runningMode) ) {
487 auto &rmode = std::get<running_t>( _runningMode );
488 if ( rmode._partialHelper )
489 rmode._partialHelper->finalize();
490 }
491 }
492
493 void NetworkRequestPrivate::setResult( NetworkRequestError &&err )
494 {
495 finished_t resState;
496 resState._result = std::move(err);
497
498 if ( std::holds_alternative<running_t>(_runningMode) ) {
499
500 auto &rmode = std::get<running_t>( _runningMode );
501 resState._downloaded = rmode._downloaded;
502 resState._contentLenght = rmode._contentLenght;
503
504 if ( resState._result.type() == NetworkRequestError::NoError && !(_options & NetworkRequest::HeadRequest) && !(_options & NetworkRequest::ConnectionTest) ) {
505 if ( _requestedRanges.size( ) ) {
506 //we have a successful download lets see if we got everything we needed
507 if ( !rmode._partialHelper->verifyData() ){
508 NetworkRequestError::Type err = rmode._partialHelper->lastError();
509 resState._result = NetworkRequestErrorPrivate::customError( err, std::string(rmode._partialHelper->lastErrorMessage()) );
510 }
511
512 // if we have ranges we need to fill our digest from the full file
513 if ( _fileVerification && resState._result.type() == NetworkRequestError::NoError ) {
514 if ( fseek( rmode._outFile, 0, SEEK_SET ) != 0 ) {
515 resState._result = NetworkRequestErrorPrivate::customError( NetworkRequestError::InternalError, "Unable to set output file pointer." );
516 } else {
517 constexpr size_t bufSize = 4096;
518 char buf[bufSize];
519 while( auto cnt = fread(buf, 1, bufSize, rmode._outFile ) > 0 ) {
520 _fileVerification->_fileDigest.update(buf, cnt);
521 }
522 }
523 }
524 } // if ( _requestedRanges.size( ) )
525 }
526
527 // finally check the file digest if we have one
528 if ( _fileVerification && resState._result.type() == NetworkRequestError::NoError ) {
529 const UByteArray &calcSum = _fileVerification->_fileDigest.digestVector ();
530 const UByteArray &expSum = zypp::Digest::hexStringToUByteArray( _fileVerification->_fileChecksum.checksum () );
531 if ( calcSum != expSum ) {
532 resState._result = NetworkRequestErrorPrivate::customError(
533 NetworkRequestError::InvalidChecksum
534 , (zypp::str::Format("Invalid file checksum %1%, expected checksum %2%")
535 % _fileVerification->_fileDigest.digest()
536 % _fileVerification->_fileChecksum.checksum () ) );
537 }
538 }
539
540 rmode._outFile.reset();
541 }
542
543 _runningMode = std::move( resState );
544 _sigFinished.emit( *z_func(), std::get<finished_t>(_runningMode)._result );
545 }
546
547 void NetworkRequestPrivate::reset()
548 {
549 _protocolMode = ProtocolMode::Default;
550 _headers.reset( nullptr );
551 _errorBuf.fill( 0 );
552 _runningMode = pending_t();
553
554 if ( _fileVerification )
555 _fileVerification->_fileDigest.reset ();
556
557 std::for_each( _requestedRanges.begin (), _requestedRanges.end(), []( CurlMultiPartHandler::Range &range ) {
558 range.restart();
559 });
560 }
561
562 void NetworkRequestPrivate::onActivityTimeout( Timer &t )
563 {
564 MIL_MEDIA << _easyHandle << " Request timeout interval: " << t.interval()<< " remaining: " << t.remaining() << std::endl;
565 std::map<std::string, boost::any> extraInfo;
566 extraInfo.insert( {"requestUrl", _url } );
567 extraInfo.insert( {"filepath", _targetFile } );
568 _dispatcher->cancel( *z_func(), NetworkRequestErrorPrivate::customError( NetworkRequestError::Timeout, "Download timed out", std::move(extraInfo) ) );
569 }
570
571 std::string NetworkRequestPrivate::errorMessage() const
572 {
573 return std::string( _errorBuf.data() );
574 }
575
576 void NetworkRequestPrivate::resetActivityTimer()
577 {
578 if ( std::holds_alternative<running_t>( _runningMode ) ){
579 auto &rmode = std::get<running_t>( _runningMode );
580 if ( rmode._activityTimer && rmode._activityTimer->isRunning() )
581 rmode._activityTimer->start();
582 }
583 }
584
585 int NetworkRequestPrivate::curlProgressCallback( void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow )
586 {
587 if ( !clientp )
588 return CURLE_OK;
589 NetworkRequestPrivate *that = reinterpret_cast<NetworkRequestPrivate *>( clientp );
590
591 if ( !std::holds_alternative<running_t>(that->_runningMode) ){
592 DBG << that->_easyHandle << " " << "Curl progress callback was called in invalid state "<< that->z_func()->state() << std::endl;
593 return -1;
594 }
595 auto &rmode = std::get<running_t>( that->_runningMode );
596
597 //reset the timer
598 that->resetActivityTimer();
599
600 rmode._isInCallback = true;
601 if ( rmode._lastProgressNow != dlnow ) {
602 rmode._lastProgressNow = dlnow;
603 that->_sigProgress.emit( *that->z_func(), dltotal, dlnow, ultotal, ulnow );
604 }
605 rmode._isInCallback = false;
606
607 return rmode._cachedResult ? CURLE_ABORTED_BY_CALLBACK : CURLE_OK;
608 }
609
610 size_t NetworkRequestPrivate::headerfunction( char *ptr, size_t bytes )
611 {
612 //it is valid to call this function with no data to write, just return OK
613 if ( bytes == 0)
614 return 0;
615
616 resetActivityTimer();
617
618 if ( _protocolMode == ProtocolMode::HTTP ) {
619
620 std::string_view hdr( ptr, bytes );
621
622 hdr.remove_prefix( std::min( hdr.find_first_not_of(" \t\r\n"), hdr.size() ) );
623 const auto lastNonWhitespace = hdr.find_last_not_of(" \t\r\n");
624 if ( lastNonWhitespace != hdr.npos )
625 hdr.remove_suffix( hdr.size() - (lastNonWhitespace + 1) );
626 else
627 hdr = std::string_view();
628
629 if ( !std::holds_alternative<running_t>(_runningMode) ){
630 DBG << _easyHandle << " " << "Curl headerfunction callback was called in invalid state "<< z_func()->state() << std::endl;
631 return -1;
632 }
633 auto &rmode = std::get<running_t>( _runningMode );
634 if ( !hdr.size() ) {
635 return ( bytes );
636 }
637 if ( _expectedFileSize && rmode._partialHelper ) {
638 const auto &repSize = rmode._partialHelper->reportedFileSize ();
639 if ( repSize && repSize != _expectedFileSize ) {
640 rmode._cachedResult = NetworkRequestErrorPrivate::customError( NetworkRequestError::InternalError, "Reported downloaded data length is not what was expected." );
641 return 0;
642 }
643 }
644 if ( zypp::strv::hasPrefixCI( hdr, "HTTP/" ) ) {
645
646 long statuscode = 0;
647 (void)curl_easy_getinfo( _easyHandle, CURLINFO_RESPONSE_CODE, &statuscode);
648
649 // if we have a status 204 we need to create a empty file
650 if( statuscode == 204 && !( _options & NetworkRequest::ConnectionTest ) && !( _options & NetworkRequest::HeadRequest ) )
651 assertOutputFile();
652
653 } else if ( zypp::strv::hasPrefixCI( hdr, "Location:" ) ) {
654 _lastRedirect = hdr.substr( 9 );
655 DBG << _easyHandle << " " << "redirecting to " << _lastRedirect << std::endl;
656
657 } else if ( zypp::strv::hasPrefixCI( hdr, "Content-Length:") ) {
658 auto lenStr = str::trim( hdr.substr( 15 ), zypp::str::TRIM );
659 auto str = std::string ( lenStr.data(), lenStr.length() );
660 auto len = zypp::str::strtonum<typename zypp::ByteCount::SizeType>( str.data() );
661 if ( len > 0 ) {
662 DBG << _easyHandle << " " << "Got Content-Length Header: " << len << std::endl;
663 rmode._contentLenght = zypp::ByteCount(len, zypp::ByteCount::B);
664 }
665 }
666 }
667
668 return bytes;
669 }
670
671 size_t NetworkRequestPrivate::writefunction( char *data, std::optional<off_t> offset, size_t max )
672 {
673 //it is valid to call this function with no data to write, just return OK
674 if ( max == 0)
675 return 0;
676
677 resetActivityTimer();
678
679 //in case of a HEAD request, we do not write anything
680 if ( _options & NetworkRequest::HeadRequest ) {
681 return ( max );
682 }
683
684 if ( !std::holds_alternative<running_t>(_runningMode) ){
685 DBG << _easyHandle << " " << "Curl writefunction callback was called in invalid state "<< z_func()->state() << std::endl;
686 return -1;
687 }
688 auto &rmode = std::get<running_t>( _runningMode );
689
690 // if we have no open file create or open it
691 if ( !assertOutputFile() )
692 return 0;
693
694 if ( offset ) {
695 // seek to the given offset
696 if ( fseek( rmode._outFile, *offset, SEEK_SET ) != 0 ) {
697 rmode._cachedResult = NetworkRequestErrorPrivate::customError( NetworkRequestError::InternalError,
698 "Unable to set output file pointer." );
699 return 0;
700 }
701 rmode._currentFileOffset = *offset;
702 }
703
704 if ( _expectedFileSize && rmode._partialHelper ) {
705 const auto &repSize = rmode._partialHelper->reportedFileSize ();
706 if ( repSize && repSize != _expectedFileSize ) {
707 rmode._cachedResult = NetworkRequestErrorPrivate::customError( NetworkRequestError::InternalError, "Reported downloaded data length is not what was expected." );
708 return 0;
709 }
710 }
711
712 //make sure we do not write after the expected file size
713 if ( _expectedFileSize && static_cast<zypp::ByteCount::SizeType>( rmode._currentFileOffset + max) > _expectedFileSize ) {
714 rmode._cachedResult = NetworkRequestErrorPrivate::customError( NetworkRequestError::ExceededMaxLen, "Downloaded data exceeds expected length." );
715 return 0;
716 }
717
718 auto written = fwrite( data, 1, max, rmode._outFile );
719 if ( written == 0 )
720 return 0;
721
722 // if we are not downloading in ranges, we can update the file digest on the fly if we have one
723 if ( !rmode._partialHelper && _fileVerification ) {
724 _fileVerification->_fileDigest.update( data, written );
725 }
726
727 rmode._currentFileOffset += written;
728
729 // count the number of real bytes we have downloaded so far
730 rmode._downloaded += written;
731 _sigBytesDownloaded.emit( *z_func(), rmode._downloaded );
732
733 return written;
734 }
735
736 void NetworkRequestPrivate::notifyErrorCodeChanged()
737 {
738 auto rmode = std::get_if<NetworkRequestPrivate::running_t>( &_runningMode );
739 if ( !rmode || !rmode->_partialHelper || !rmode->_partialHelper->hasError() )
740 return;
741
742 // oldest cached result wins
743 if ( rmode->_cachedResult )
744 return;
745
746 auto lastErr = NetworkRequestErrorPrivate::customError( rmode->_partialHelper->lastError() , std::string(rmode->_partialHelper->lastErrorMessage()) );
747 MIL_MEDIA << _easyHandle << " Multipart handler announced error code " << lastErr.toString () << std::endl;
748 rmode->_cachedResult = lastErr;
749 }
750
751 ZYPP_IMPL_PRIVATE(NetworkRequest)
752
753 NetworkRequest::NetworkRequest(zyppng::Url url, zypp::filesystem::Pathname targetFile, zyppng::NetworkRequest::FileMode fMode)
754 : Base ( *new NetworkRequestPrivate( std::move(url), std::move(targetFile), std::move(fMode), *this ) )
755 {
756 }
757
758 NetworkRequest::~NetworkRequest()
759 {
760 Z_D();
761
762 if ( d->_dispatcher )
763 d->_dispatcher->cancel( *this, "Request destroyed while still running" );
764 }
765
766 void NetworkRequest::setExpectedFileSize( zypp::ByteCount expectedFileSize )
767 {
768 d_func()->_expectedFileSize = std::move( expectedFileSize );
769 }
770
771 zypp::ByteCount NetworkRequest::expectedFileSize() const
772 {
773 return d_func()->_expectedFileSize;
774 }
775
776 void NetworkRequest::setPriority( NetworkRequest::Priority prio, bool triggerReschedule )
777 {
778 Z_D();
779 d->_priority = prio;
780 if ( state() == Pending && triggerReschedule && d->_dispatcher )
781 d->_dispatcher->reschedule();
782 }
783
784 NetworkRequest::Priority NetworkRequest::priority() const
785 {
786 return d_func()->_priority;
787 }
788
789 void NetworkRequest::setOptions( Options opt )
790 {
791 d_func()->_options = opt;
792 }
793
794 NetworkRequest::Options NetworkRequest::options() const
795 {
796 return d_func()->_options;
797 }
798
799 void NetworkRequest::addRequestRange(size_t start, size_t len, std::optional<zypp::Digest> &&digest, CheckSumBytes expectedChkSum , std::any userData, std::optional<size_t> digestCompareLen, std::optional<size_t> chksumpad )
800 {
801 Z_D();
802 if ( state() == Running )
803 return;
804
805 d->_requestedRanges.push_back( Range::make( start, len, std::move(digest), std::move( expectedChkSum ), std::move( userData ), digestCompareLen, chksumpad ) );
806 }
807
808 void NetworkRequest::addRequestRange(zyppng::NetworkRequest::Range &&range )
809 {
810 Z_D();
811 if ( state() == Running )
812 return;
813
814 d->_requestedRanges.push_back( std::move(range) );
815 auto &rng = d->_requestedRanges.back();
816 rng._rangeState = CurlMultiPartHandler::Pending;
817 rng.bytesWritten = 0;
818 if ( rng._digest )
819 rng._digest->reset();
820 }
821
822 bool NetworkRequest::setExpectedFileChecksum( const zypp::CheckSum &expected )
823 {
824 Z_D();
825 if ( state() == Running )
826 return false;
827
828 zypp::Digest fDig;
829 if ( !fDig.create( expected.type () ) )
830 return false;
831
832 d->_fileVerification = NetworkRequestPrivate::FileVerifyInfo{
833 ._fileDigest = std::move(fDig),
834 ._fileChecksum = expected
835 };
836 return true;
837 }
838
839 void NetworkRequest::resetRequestRanges()
840 {
841 Z_D();
842 if ( state() == Running )
843 return;
844 d->_requestedRanges.clear();
845 }
846
847 std::vector<NetworkRequest::Range> NetworkRequest::failedRanges() const
848 {
849 const auto mystate = state();
850 if ( mystate != Finished && mystate != Error )
851 return {};
852
853 Z_D();
854
855 std::vector<Range> failed;
856 for ( auto &r : d->_requestedRanges ) {
857 if ( r._rangeState != CurlMultiPartHandler::Finished ) {
858 failed.push_back( r.clone() );
859 }
860 }
861 return failed;
862 }
863
864 const std::vector<NetworkRequest::Range> &NetworkRequest::requestedRanges() const
865 {
866 return d_func()->_requestedRanges;
867 }
868
869 const std::string &NetworkRequest::lastRedirectInfo() const
870 {
871 return d_func()->_lastRedirect;
872 }
873
874 void *NetworkRequest::nativeHandle() const
875 {
876 return d_func()->_easyHandle;
877 }
878
879 std::optional<zyppng::NetworkRequest::Timings> NetworkRequest::timings() const
880 {
881 const auto myerr = error();
882 const auto mystate = state();
883 if ( mystate != Finished )
884 return {};
885
886 Timings t;
887
888 auto getMeasurement = [ this ]( const CURLINFO info, std::chrono::microseconds &target ){
889 using FPSeconds = std::chrono::duration<double, std::chrono::seconds::period>;
890 double val = 0;
891 const auto res = curl_easy_getinfo( d_func()->_easyHandle, info, &val );
892 if ( CURLE_OK == res ) {
893 target = std::chrono::duration_cast<std::chrono::microseconds>( FPSeconds(val) );
894 }
895 };
896
897 getMeasurement( CURLINFO_NAMELOOKUP_TIME, t.namelookup );
898 getMeasurement( CURLINFO_CONNECT_TIME, t.connect);
899 getMeasurement( CURLINFO_APPCONNECT_TIME, t.appconnect);
900 getMeasurement( CURLINFO_PRETRANSFER_TIME , t.pretransfer);
901 getMeasurement( CURLINFO_TOTAL_TIME, t.total);
902 getMeasurement( CURLINFO_REDIRECT_TIME, t.redirect);
903
904 return t;
905 }
906
907 std::vector<char> NetworkRequest::peekData( off_t offset, size_t count ) const
908 {
909 Z_D();
910
911 if ( !std::holds_alternative<NetworkRequestPrivate::running_t>( d->_runningMode) )
912 return {};
913
914 const auto &rmode = std::get<NetworkRequestPrivate::running_t>( d->_runningMode );
915 return zypp::io::peek_data_fd( rmode._outFile, offset, count );
916 }
917
918 Url NetworkRequest::url() const
919 {
920 return d_func()->_url;
921 }
922
923 void NetworkRequest::setUrl(const Url &url)
924 {
925 Z_D();
926 if ( state() == NetworkRequest::Running )
927 return;
928
929 d->_url = url;
930 }
931
932 const zypp::filesystem::Pathname &NetworkRequest::targetFilePath() const
933 {
934 return d_func()->_targetFile;
935 }
936
937 void NetworkRequest::setTargetFilePath( const zypp::filesystem::Pathname &path )
938 {
939 Z_D();
940 if ( state() == NetworkRequest::Running )
941 return;
942 d->_targetFile = path;
943 }
944
945 NetworkRequest::FileMode NetworkRequest::fileOpenMode() const
946 {
947 return d_func()->_fMode;
948 }
949
950 void NetworkRequest::setFileOpenMode( FileMode mode )
951 {
952 Z_D();
953 if ( state() == NetworkRequest::Running )
954 return;
955 d->_fMode = std::move( mode );
956 }
957
958 std::string NetworkRequest::contentType() const
959 {
960 char *ptr = NULL;
961 if ( curl_easy_getinfo( d_func()->_easyHandle, CURLINFO_CONTENT_TYPE, &ptr ) == CURLE_OK && ptr )
962 return std::string(ptr);
963 return std::string();
964 }
965
966 zypp::ByteCount NetworkRequest::reportedByteCount() const
967 {
968 return std::visit([](auto& arg) -> zypp::ByteCount {
969 using T = std::decay_t<decltype(arg)>;
970 if constexpr (std::is_same_v<T, NetworkRequestPrivate::pending_t> || std::is_same_v<T, NetworkRequestPrivate::prepareNextRangeBatch_t> )
971 return zypp::ByteCount(0);
972 else if constexpr (std::is_same_v<T, NetworkRequestPrivate::running_t>
973 || std::is_same_v<T, NetworkRequestPrivate::finished_t>)
974 return arg._contentLenght;
975 else
976 static_assert(always_false<T>::value, "Unhandled state type");
977 }, d_func()->_runningMode);
978 }
979
980 zypp::ByteCount NetworkRequest::downloadedByteCount() const
981 {
982 return std::visit([](auto& arg) -> zypp::ByteCount {
983 using T = std::decay_t<decltype(arg)>;
984 if constexpr (std::is_same_v<T, NetworkRequestPrivate::pending_t>)
985 return zypp::ByteCount();
986 else if constexpr (std::is_same_v<T, NetworkRequestPrivate::running_t>
987 || std::is_same_v<T, NetworkRequestPrivate::prepareNextRangeBatch_t>
988 || std::is_same_v<T, NetworkRequestPrivate::finished_t>)
989 return arg._downloaded;
990 else
991 static_assert(always_false<T>::value, "Unhandled state type");
992 }, d_func()->_runningMode);
993 }
994
995 TransferSettings &NetworkRequest::transferSettings()
996 {
997 return d_func()->_settings;
998 }
999
1000 NetworkRequest::State NetworkRequest::state() const
1001 {
1002 return std::visit([this](auto& arg) {
1003 using T = std::decay_t<decltype(arg)>;
1004 if constexpr (std::is_same_v<T, NetworkRequestPrivate::pending_t>)
1005 return Pending;
1006 else if constexpr (std::is_same_v<T, NetworkRequestPrivate::running_t> || std::is_same_v<T, NetworkRequestPrivate::prepareNextRangeBatch_t> )
1007 return Running;
1008 else if constexpr (std::is_same_v<T, NetworkRequestPrivate::finished_t>) {
1009 if ( std::get<NetworkRequestPrivate::finished_t>( d_func()->_runningMode )._result.isError() )
1010 return Error;
1011 else
1012 return Finished;
1013 }
1014 else
1015 static_assert(always_false<T>::value, "Unhandled state type");
1016 }, d_func()->_runningMode);
1017 }
1018
1019 NetworkRequestError NetworkRequest::error() const
1020 {
1021 const auto s = state();
1022 if ( s != Error && s != Finished )
1023 return NetworkRequestError();
1024 return std::get<NetworkRequestPrivate::finished_t>( d_func()->_runningMode)._result;
1025 }
1026
1027 std::string NetworkRequest::extendedErrorString() const
1028 {
1029 if ( !hasError() )
1030 return std::string();
1031
1032 return error().nativeErrorString();
1033 }
1034
1035 bool NetworkRequest::hasError() const
1036 {
1037 return error().isError();
1038 }
1039
1040 bool NetworkRequest::addRequestHeader( const std::string &header )
1041 {
1042 Z_D();
1043
1044 curl_slist *res = curl_slist_append( d->_headers ? d->_headers.get() : nullptr, header.c_str() );
1045 if ( !res )
1046 return false;
1047
1048 if ( !d->_headers )
1049 d->_headers = std::unique_ptr< curl_slist, decltype (&curl_slist_free_all) >( res, &curl_slist_free_all );
1050
1051 return true;
1052 }
1053
1054 const zypp::Pathname &NetworkRequest::cookieFile() const
1055 {
1056 return d_func()->_currentCookieFile;
1057 }
1058
1059 void NetworkRequest::setCookieFile(zypp::Pathname cookieFile )
1060 {
1061 d_func()->_currentCookieFile = std::move(cookieFile);
1062 }
1063
1064 SignalProxy<void (NetworkRequest &req)> NetworkRequest::sigStarted()
1065 {
1066 return d_func()->_sigStarted;
1067 }
1068
1069 SignalProxy<void (NetworkRequest &req, zypp::ByteCount count)> NetworkRequest::sigBytesDownloaded()
1070 {
1071 return d_func()->_sigBytesDownloaded;
1072 }
1073
1074 SignalProxy<void (NetworkRequest &req, off_t dltotal, off_t dlnow, off_t ultotal, off_t ulnow)> NetworkRequest::sigProgress()
1075 {
1076 return d_func()->_sigProgress;
1077 }
1078
1079 SignalProxy<void (zyppng::NetworkRequest &req, const zyppng::NetworkRequestError &err)> NetworkRequest::sigFinished()
1080 {
1081 return d_func()->_sigFinished;
1082 }
1083
1084}
ZYPP_CAUGHT
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition Exception.h:475
ZYPP_THROW
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition Exception.h:459
IOTools.h
DBG
#define DBG
Definition Logger.h:102
MIL
#define MIL
Definition Logger.h:103
Pathname.h
StringV.h
String.h
zypp::ByteCount
Store and operate with byte count.
Definition ByteCount.h:32
zypp::ByteCount::SizeType
Unit::ValueType SizeType
Definition ByteCount.h:38
zypp::ByteCount::B
static const Unit B
1 Byte
Definition ByteCount.h:43
zypp::CheckSum
Definition CheckSum.h:34
zypp::Digest
Compute Message Digests (MD5, SHA1 etc).
Definition Digest.h:38
zypp::Digest::create
bool create(const std::string &name)
initialize creation of a new message digest
Definition Digest.cc:198
zypp::Exception
Base class for Exception.
Definition Exception.h:153
zypp::Exception::asString
std::string asString() const
Error message provided by dumpOn as string.
Definition Exception.cc:124
zypp::UByteArray
Definition ByteArray.h:46
zypp::Url
Url manipulation class.
Definition Url.h:93
zypp::filesystem::Pathname
Pathname.
Definition Pathname.h:48
zypp::filesystem::Pathname::c_str
const char * c_str() const
String representation.
Definition Pathname.h:113
zypp::filesystem::Pathname::empty
bool empty() const
Test for an empty path.
Definition Pathname.h:117
zypp::media::CurlAuthData::auth_type_str2long
static long auth_type_str2long(std::string &auth_type_str)
Converts a string of comma separated list of authetication type names into a long of ORed CURLAUTH_* ...
Definition curlauthdata.cc:50
zypp::media::MediaCurlInitException
Definition mediaexception.h:227
zypp::media::MediaCurlSetOptException
Definition mediaexception.h:385
zypp::media::TransferSettings::password
const std::string & password() const
auth password
Definition transfersettings.cc:175
zypp::media::TransferSettings::maxDownloadSpeed
long maxDownloadSpeed() const
Maximum download speed (bytes per second).
Definition transfersettings.cc:261
zypp::media::TransferSettings::connectTimeout
long connectTimeout() const
connection timeout
Definition transfersettings.cc:240
zypp::media::TransferSettings::timeout
long timeout() const
transfer timeout
Definition transfersettings.cc:233
zypp::media::TransferSettings::clientCertificatePath
const Pathname & clientCertificatePath() const
SSL client certificate file.
Definition transfersettings.cc:291
zypp::media::TransferSettings::minDownloadSpeed
long minDownloadSpeed() const
Minimum download speed (bytes per second) until the connection is dropped.
Definition transfersettings.cc:254
zypp::media::TransferSettings::headers
const Headers & headers() const
returns a list of all added headers (trimmed)
Definition transfersettings.cc:141
zypp::media::TransferSettings::proxy
const std::string & proxy() const
proxy host
Definition transfersettings.cc:198
zypp::media::TransferSettings::clientKeyPath
const Pathname & clientKeyPath() const
SSL client key file.
Definition transfersettings.cc:301
zypp::media::TransferSettings::setUserAgentString
void setUserAgentString(std::string &&val_r)
sets the user agent ie: "Mozilla v3" (trims)
Definition transfersettings.cc:150
zypp::media::TransferSettings::addHeader
void addHeader(std::string &&val_r)
add a header, on the form "Foo: Bar" (trims)
Definition transfersettings.cc:138
zypp::media::TransferSettings::proxyUserPassword
std::string proxyUserPassword() const
returns the proxy user and password as a user:pass string
Definition transfersettings.cc:220
zypp::media::TransferSettings::verifyHostEnabled
bool verifyHostEnabled() const
Whether to verify host for ssl.
Definition transfersettings.cc:275
zypp::media::TransferSettings::userAgentString
const std::string & userAgentString() const
user agent string (trimmed)
Definition transfersettings.cc:153
zypp::media::TransferSettings::hasCredentials
bool hasCredentials() const
has a username, maybe even the password
Definition transfersettings.cc:157
zypp::media::TransferSettings::cookieFileEnabled
bool cookieFileEnabled() const
Definition transfersettings.cc:307
zypp::media::TransferSettings::proxyEnabled
bool proxyEnabled() const
proxy is enabled
Definition transfersettings.cc:188
zypp::media::TransferSettings::username
const std::string & username() const
auth username
Definition transfersettings.cc:166
zypp::media::TransferSettings::certificateAuthoritiesPath
const Pathname & certificateAuthoritiesPath() const
SSL certificate authorities path ( default: /etc/ssl/certs ).
Definition transfersettings.cc:316
zypp::media::TransferSettings::logCredentials
std::ostream & logCredentials(std::ostream &str) const
log credentials to stream hiding the password.
Definition transfersettings.h:67
zypp::media::TransferSettings::verifyPeerEnabled
bool verifyPeerEnabled() const
Whether to verify peer for ssl.
Definition transfersettings.cc:282
zyppng::BasePrivate::BasePrivate
BasePrivate(Base &b)
Definition base_p.h:17
zyppng::Base::Base
Base()
Definition base.cc:20
zyppng::CurlMultiPartHandler
The CurlMultiPartHandler class.
Definition curlmultiparthandler.h:70
zyppng::CurlMultiPartHandler::prepare
bool prepare()
Definition curlmultiparthandler.cc:522
zyppng::CurlMultiPartHandler::lastErrorMessage
const std::string & lastErrorMessage() const
Definition curlmultiparthandler.cc:466
zyppng::CurlMultiPartHandler::Pending
@ Pending
Definition curlmultiparthandler.h:95
zyppng::CurlMultiPartHandler::Finished
@ Finished
Definition curlmultiparthandler.h:97
zyppng::CurlMultiPartHandler::ProtocolMode::HTTP
@ HTTP
Definition curlmultiparthandler.h:75
zyppng::CurlMultiPartHandler::ProtocolMode::Basic
@ Basic
Definition curlmultiparthandler.h:74
zyppng::NetworkRequestErrorPrivate::customError
static zyppng::NetworkRequestError customError(NetworkRequestError::Type t, std::string &&errorMsg="", std::map< std::string, boost::any > &&extraInfo={})
Definition networkrequesterror.cc:34
zyppng::NetworkRequestError
The NetworkRequestError class Represents a error that occured in.
Definition networkrequesterror.h:24
zyppng::NetworkRequestError::type
Type type() const
type Returns the type of the error
Definition networkrequesterror.cc:230
zyppng::NetworkRequestError::nativeErrorString
std::string nativeErrorString() const
Definition networkrequesterror.cc:297
zyppng::NetworkRequestError::Type
Type
Definition networkrequesterror.h:26
zyppng::NetworkRequestError::InternalError
@ InternalError
Definition networkrequesterror.h:28
zyppng::NetworkRequestError::ExceededMaxLen
@ ExceededMaxLen
Definition networkrequesterror.h:32
zyppng::NetworkRequestError::RangeFail
@ RangeFail
Definition networkrequesterror.h:44
zyppng::NetworkRequestError::Timeout
@ Timeout
Definition networkrequesterror.h:37
zyppng::NetworkRequestError::NoError
@ NoError
Definition networkrequesterror.h:27
zyppng::NetworkRequestError::InvalidChecksum
@ InvalidChecksum
Definition networkrequesterror.h:33
zyppng::NetworkRequestError::isError
bool isError() const
isError Will return true if this is a actual error
Definition networkrequesterror.cc:240
zyppng::NetworkRequestPrivate
Definition request_p.h:35
zyppng::NetworkRequestPrivate::headerfunction
size_t headerfunction(char *ptr, size_t bytes) override
Definition request.cc:610
zyppng::NetworkRequestPrivate::_easyHandle
void * _easyHandle
Definition request_p.h:125
zyppng::NetworkRequestPrivate::_fileVerification
std::optional< FileVerifyInfo > _fileVerification
The digest for the full file.
Definition request_p.h:117
zyppng::NetworkRequestPrivate::_protocolMode
enum zyppng::NetworkRequestPrivate::ProtocolMode _protocolMode
zyppng::NetworkRequestPrivate::notifyErrorCodeChanged
void notifyErrorCodeChanged() override
Definition request.cc:736
zyppng::NetworkRequestPrivate::_url
Url _url
Definition request_p.h:106
zyppng::NetworkRequestPrivate::_targetFile
zypp::Pathname _targetFile
Definition request_p.h:107
zyppng::NetworkRequestPrivate::resetActivityTimer
void resetActivityTimer()
Definition request.cc:576
zyppng::NetworkRequestPrivate::_currentCookieFile
zypp::Pathname _currentCookieFile
Definition request_p.h:123
zyppng::NetworkRequestPrivate::_sigBytesDownloaded
Signal< void(NetworkRequest &req, zypp::ByteCount count)> _sigBytesDownloaded
Definition request_p.h:130
zyppng::NetworkRequestPrivate::_dispatcher
NetworkRequestDispatcher * _dispatcher
Definition request_p.h:126
zyppng::NetworkRequestPrivate::_requestedRanges
std::vector< NetworkRequest::Range > _requestedRanges
the requested ranges that need to be downloaded
Definition request_p.h:111
zyppng::NetworkRequestPrivate::writefunction
size_t writefunction(char *ptr, std::optional< off_t > offset, size_t bytes) override
Definition request.cc:671
zyppng::NetworkRequestPrivate::curlProgressCallback
static int curlProgressCallback(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
Definition request.cc:585
zyppng::NetworkRequestPrivate::errorMessage
std::string errorMessage() const
Definition request.cc:571
zyppng::NetworkRequestPrivate::_sigStarted
Signal< void(NetworkRequest &req)> _sigStarted
Definition request_p.h:129
zyppng::NetworkRequestPrivate::_fMode
NetworkRequest::FileMode _fMode
Definition request_p.h:119
zyppng::NetworkRequestPrivate::_runningMode
std::variant< pending_t, running_t, prepareNextRangeBatch_t, finished_t > _runningMode
Definition request_p.h:188
zyppng::NetworkRequestPrivate::initialize
bool initialize(std::string &errBuf)
Definition request.cc:92
zyppng::NetworkRequestPrivate::onActivityTimeout
void onActivityTimeout(Timer &)
Definition request.cc:562
zyppng::NetworkRequestPrivate::_sigProgress
Signal< void(NetworkRequest &req, off_t dltotal, off_t dlnow, off_t ultotal, off_t ulnow)> _sigProgress
Definition request_p.h:131
zyppng::NetworkRequestPrivate::dequeueNotify
void dequeueNotify()
Definition request.cc:484
zyppng::NetworkRequestPrivate::_lastRedirect
std::string _lastRedirect
to log/report redirections
Definition request_p.h:122
zyppng::NetworkRequestPrivate::_options
NetworkRequest::Options _options
Definition request_p.h:109
zyppng::NetworkRequestPrivate::prepareToContinue
bool prepareToContinue(std::string &errBuf)
Definition request.cc:416
zyppng::NetworkRequestPrivate::ProtocolMode::HTTP
@ HTTP
Definition request_p.h:40
zyppng::NetworkRequestPrivate::ProtocolMode::Default
@ Default
Definition request_p.h:39
zyppng::NetworkRequestPrivate::setResult
void setResult(NetworkRequestError &&err)
Definition request.cc:493
zyppng::NetworkRequestPrivate::assertOutputFile
bool assertOutputFile()
Definition request.cc:378
zyppng::NetworkRequestPrivate::~NetworkRequestPrivate
~NetworkRequestPrivate() override
Definition request.cc:81
zyppng::NetworkRequestPrivate::_errorBuf
std::array< char, CURL_ERROR_SIZE+1 > _errorBuf
Definition request_p.h:95
zyppng::NetworkRequestPrivate::reset
void reset()
Definition request.cc:547
zyppng::NetworkRequestPrivate::canRecover
bool canRecover() const
Definition request.cc:408
zyppng::NetworkRequestPrivate::setupHandle
bool setupHandle(std::string &errBuf)
Definition request.cc:105
zyppng::NetworkRequestPrivate::NetworkRequestPrivate
NetworkRequestPrivate(Url &&url, zypp::Pathname &&targetFile, NetworkRequest::FileMode fMode, NetworkRequest &p)
Definition request.cc:73
zyppng::NetworkRequestPrivate::hasMoreWork
bool hasMoreWork() const
Definition request.cc:456
zyppng::NetworkRequestPrivate::_settings
TransferSettings _settings
Definition request_p.h:108
zyppng::NetworkRequestPrivate::setCurlOption
void setCurlOption(CURLoption opt, T data)
Definition request_p.h:98
zyppng::NetworkRequestPrivate::_expectedFileSize
zypp::ByteCount _expectedFileSize
Definition request_p.h:110
zyppng::NetworkRequestPrivate::_sigFinished
Signal< void(NetworkRequest &req, const NetworkRequestError &err)> _sigFinished
Definition request_p.h:132
zyppng::NetworkRequestPrivate::aboutToStart
void aboutToStart()
Definition request.cc:462
zyppng::NetworkRequestPrivate::_headers
std::unique_ptr< curl_slist, decltype(&curl_slist_free_all) > _headers
Definition request_p.h:140
zyppng::NetworkRequest
Definition request.h:43
zyppng::NetworkRequest::setExpectedFileChecksum
bool setExpectedFileChecksum(const zypp::CheckSum &expected)
Definition request.cc:822
zyppng::NetworkRequest::reportedByteCount
zypp::ByteCount reportedByteCount() const
Returns the number of bytes that are reported from the backend as the full download size,...
Definition request.cc:966
zyppng::NetworkRequest::targetFilePath
const zypp::Pathname & targetFilePath() const
Returns the target filename path.
Definition request.cc:932
zyppng::NetworkRequest::downloadedByteCount
zypp::ByteCount downloadedByteCount() const
Returns the number of already downloaded bytes as reported by the backend.
Definition request.cc:980
zyppng::NetworkRequest::resetRequestRanges
void resetRequestRanges()
Definition request.cc:839
zyppng::NetworkRequest::setUrl
void setUrl(const Url &url)
This will change the URL of the request.
Definition request.cc:923
zyppng::NetworkRequest::setExpectedFileSize
void setExpectedFileSize(zypp::ByteCount expectedFileSize)
Definition request.cc:766
zyppng::NetworkRequest::setPriority
void setPriority(Priority prio, bool triggerReschedule=true)
Definition request.cc:776
zyppng::NetworkRequest::peekData
std::vector< char > peekData(off_t offset, size_t count) const
Definition request.cc:907
zyppng::NetworkRequest::HeadRequest
@ HeadRequest
Definition request.h:71
zyppng::NetworkRequest::ConnectionTest
@ ConnectionTest
Definition request.h:72
zyppng::NetworkRequest::State
State
Definition request.h:51
zyppng::NetworkRequest::Running
@ Running
Definition request.h:53
zyppng::NetworkRequest::Error
@ Error
Definition request.h:55
zyppng::NetworkRequest::Finished
@ Finished
Definition request.h:54
zyppng::NetworkRequest::Pending
@ Pending
Definition request.h:52
zyppng::NetworkRequest::contentType
std::string contentType() const
Returns the content type as reported from the server.
Definition request.cc:958
zyppng::NetworkRequest::setFileOpenMode
void setFileOpenMode(FileMode mode)
Sets the file open mode to mode.
Definition request.cc:950
zyppng::NetworkRequest::addRequestHeader
bool addRequestHeader(const std::string &header)
Definition request.cc:1040
zyppng::NetworkRequest::~NetworkRequest
~NetworkRequest() override
Definition request.cc:758
zyppng::NetworkRequest::setOptions
void setOptions(Options opt)
Definition request.cc:789
zyppng::NetworkRequest::url
Url url() const
Definition request.cc:918
zyppng::NetworkRequest::fileOpenMode
FileMode fileOpenMode() const
Returns the currently configured file open mode.
Definition request.cc:945
zyppng::NetworkRequest::expectedFileSize
zypp::ByteCount expectedFileSize() const
Definition request.cc:771
zyppng::NetworkRequest::hasError
bool hasError() const
Checks if there was a error with the request.
Definition request.cc:1035
zyppng::NetworkRequest::state
State state() const
Returns the current state the HttpDownloadRequest is in.
Definition request.cc:1000
zyppng::NetworkRequest::sigFinished
SignalProxy< void(NetworkRequest &req, const NetworkRequestError &err)> sigFinished()
Signals that the download finished.
Definition request.cc:1079
zyppng::NetworkRequest::CheckSumBytes
UByteArray CheckSumBytes
Definition request.h:49
zyppng::NetworkRequest::options
Options options() const
Definition request.cc:794
zyppng::NetworkRequest::sigBytesDownloaded
SignalProxy< void(NetworkRequest &req, zypp::ByteCount count)> sigBytesDownloaded()
Signals that new data has been downloaded, this is only the payload and does not include control data...
Definition request.cc:1069
zyppng::NetworkRequest::timings
std::optional< Timings > timings() const
After the request is finished query the timings that were collected during download.
Definition request.cc:879
zyppng::NetworkRequest::FileMode
FileMode
Definition request.h:64
zyppng::NetworkRequest::WriteShared
@ WriteShared
Definition request.h:66
zyppng::NetworkRequest::extendedErrorString
std::string extendedErrorString() const
In some cases, curl can provide extended error information collected at runtime.
Definition request.cc:1027
zyppng::NetworkRequest::NetworkRequest
NetworkRequest(Url url, zypp::Pathname targetFile, FileMode fMode=WriteExclusive)
Definition request.cc:753
zyppng::NetworkRequest::priority
Priority priority() const
Definition request.cc:784
zyppng::NetworkRequest::error
NetworkRequestError error() const
Returns the last set Error.
Definition request.cc:1019
zyppng::NetworkRequest::setTargetFilePath
void setTargetFilePath(const zypp::Pathname &path)
Changes the target file path of the download.
Definition request.cc:937
zyppng::NetworkRequest::cookieFile
const zypp::Pathname & cookieFile() const
Definition request.cc:1054
zyppng::NetworkRequest::nativeHandle
void * nativeHandle() const
Definition request.cc:874
zyppng::NetworkRequest::setCookieFile
void setCookieFile(zypp::Pathname cookieFile)
Definition request.cc:1059
zyppng::NetworkRequest::addRequestRange
void addRequestRange(size_t start, size_t len=0, std::optional< zypp::Digest > &&digest={}, CheckSumBytes expectedChkSum=CheckSumBytes(), std::any userData=std::any(), std::optional< size_t > digestCompareLen={}, std::optional< size_t > chksumpad={})
Definition request.cc:799
zyppng::NetworkRequest::failedRanges
std::vector< Range > failedRanges() const
Definition request.cc:847
zyppng::NetworkRequest::requestedRanges
const std::vector< Range > & requestedRanges() const
Definition request.cc:864
zyppng::NetworkRequest::sigStarted
SignalProxy< void(NetworkRequest &req)> sigStarted()
Signals that the dispatcher dequeued the request and actually starts downloading data.
Definition request.cc:1064
zyppng::NetworkRequest::sigProgress
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:1074
zyppng::NetworkRequest::transferSettings
TransferSettings & transferSettings()
Definition request.cc:995
zyppng::NetworkRequest::Range
CurlMultiPartHandler::Range Range
Definition request.h:76
zyppng::NetworkRequest::lastRedirectInfo
const std::string & lastRedirectInfo() const
Definition request.cc:869
zyppng::NetworkRequest::Priority
Priority
Definition request.h:58
zyppng::SignalProxy
Definition signals.h:325
zyppng::Timer
The Timer class provides repetitive and single-shot timers.
Definition timer.h:45
zyppng::Timer::sigExpired
SignalProxy< void(Timer &t)> sigExpired()
This signal is always emitted when the timer expires.
Definition timer.cc:120
zyppng::Timer::remaining
uint64_t remaining() const
Definition timer.cc:99
zyppng::Timer::interval
uint64_t interval() const
Definition timer.cc:94
zyppng::expected
Definition expected.h:56
curlhelper_p.h
EXPLICITLY_NO_PROXY
#define EXPLICITLY_NO_PROXY
Definition curlhelper_p.h:23
linuxhelpers_p.h
mediadebug_p.h
MIL_MEDIA
#define MIL_MEDIA
Definition mediadebug_p.h:29
DBG_MEDIA
#define DBG_MEDIA
Definition mediadebug_p.h:28
internal::curlUnEscape
std::string curlUnEscape(const std::string &text_r)
Definition curlhelper.cc:394
internal::setupZYPP_MEDIA_CURL_DEBUG
void setupZYPP_MEDIA_CURL_DEBUG(CURL *curl)
Setup CURLOPT_VERBOSE and CURLOPT_DEBUGFUNCTION according to env::ZYPP_MEDIA_CURL_DEBUG.
Definition curlhelper.cc:130
internal::setCurlRedirProtocols
CURLcode setCurlRedirProtocols(CURL *curl)
Definition curlhelper.cc:544
std
Definition ansi.h:855
std::decay_t
typename decay< T >::type decay_t
Definition TypeTraits.h:42
str
String related utilities and Regular expression matching.
zypp::env::ZYPP_MEDIA_CURL_IPRESOLVE
int ZYPP_MEDIA_CURL_IPRESOLVE()
4/6 to force IPv4/v6
Definition curlhelper.cc:45
zypp::filesystem
Types and functions for filesystem operations.
Definition Glob.cc:24
zypp::filesystem::assert_file_mode
int assert_file_mode(const Pathname &path, unsigned mode)
Like assert_file but enforce mode even if the file already exists.
Definition PathInfo.cc:1224
zypp::io::peek_data_fd
std::vector< char > peek_data_fd(FILE *fd, off_t offset, size_t count)
Definition IOTools.cc:171
zypp::str::TRIM
@ TRIM
Definition String.h:571
zypp::str::form
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
Definition String.cc:39
zypp::str::strtonum
TInt strtonum(const C_Str &str)
Parsing numbers from string.
zypp::str::trim
std::string trim(const std::string &s, const Trim trim_r)
Definition String.cc:226
zypp::target
Definition KeyRing.h:325
zypp::url
Url details namespace.
Definition UrlBase.cc:58
zypp
Easy-to use interface to the ZYPP dependency resolver.
Definition CodePitfalls.doc:2
zyppng::str::trim
T trim(StrType &&s, const Trim trim_r)
Definition string.h:35
zyppng
Definition MediaNetworkRequestExecutor.h:16
zyppng::TransferSettings
zypp::media::TransferSettings TransferSettings
Definition transfersettings.h:20
zyppng::strerr_cxx
std::string strerr_cxx(const int err=-1)
Definition linuxhelpers_p.h:14
networkrequestdispatcher.h
networkrequesterror_p.h
request_p.h
zypp::media::CurlConfig
Structure holding values of curlrc options.
Definition curlconfig.h:27
zypp::media::CurlConfig::proxyuserpwd
std::string proxyuserpwd
Definition curlconfig.h:49
zypp::media::CurlConfig::parseConfig
static int parseConfig(CurlConfig &config, const std::string &filename="")
Parse a curlrc file and store the result in the config structure.
Definition curlconfig.cc:24
zypp::str::Format
Convenient building of std::string with boost::format.
Definition String.h:254
zyppng::CurlMultiPartHandler::Range
Definition curlmultiparthandler.h:104
zyppng::CurlMultiPartHandler::Range::make
static Range make(size_t start, size_t len=0, std::optional< zypp::Digest > &&digest={}, CheckSumBytes &&expectedChkSum=CheckSumBytes(), std::any &&userData=std::any(), std::optional< size_t > digestCompareLen={}, std::optional< size_t > _dataBlockPadding={})
Definition curlmultiparthandler.cc:84
zyppng::NetworkRequestPrivate::FileVerifyInfo
Definition request_p.h:113
zyppng::NetworkRequestPrivate::finished_t
Definition request_p.h:182
zyppng::NetworkRequestPrivate::finished_t::_downloaded
off_t _downloaded
Definition request_p.h:183
zyppng::NetworkRequestPrivate::finished_t::_result
NetworkRequestError _result
Definition request_p.h:185
zyppng::NetworkRequestPrivate::finished_t::_contentLenght
zypp::ByteCount _contentLenght
Definition request_p.h:184
zyppng::NetworkRequestPrivate::pending_t
Definition request_p.h:146
zyppng::NetworkRequestPrivate::prepareNextRangeBatch_t
Definition request_p.h:152
zyppng::NetworkRequestPrivate::prepareNextRangeBatch_t::_downloaded
off_t _downloaded
Definition request_p.h:155
zyppng::NetworkRequestPrivate::prepareNextRangeBatch_t::prepareNextRangeBatch_t
prepareNextRangeBatch_t(running_t &&prevState)
Definition request.cc:57
zyppng::NetworkRequestPrivate::prepareNextRangeBatch_t::_partialHelper
std::unique_ptr< CurlMultiPartHandler > _partialHelper
Definition request_p.h:156
zyppng::NetworkRequestPrivate::prepareNextRangeBatch_t::_outFile
zypp::AutoFILE _outFile
Definition request_p.h:154
zyppng::NetworkRequestPrivate::running_t
Definition request_p.h:159
zyppng::NetworkRequestPrivate::running_t::_partialHelper
std::unique_ptr< CurlMultiPartHandler > _partialHelper
Definition request_p.h:166
zyppng::NetworkRequestPrivate::running_t::_downloaded
off_t _downloaded
Definition request_p.h:176
zyppng::NetworkRequestPrivate::running_t::running_t
running_t(pending_t &&prevState)
Definition request.cc:63
zyppng::NetworkRequestPrivate::running_t::_outFile
zypp::AutoFILE _outFile
Definition request_p.h:165
zyppng::NetworkRequest::Timings
Definition request.h:78
zyppng::NetworkRequest::Timings::appconnect
std::chrono::microseconds appconnect
Definition request.h:81
zyppng::NetworkRequest::Timings::redirect
std::chrono::microseconds redirect
Definition request.h:84
zyppng::NetworkRequest::Timings::pretransfer
std::chrono::microseconds pretransfer
Definition request.h:82
zyppng::NetworkRequest::Timings::total
std::chrono::microseconds total
Definition request.h:83
zyppng::NetworkRequest::Timings::namelookup
std::chrono::microseconds namelookup
Definition request.h:79
zyppng::NetworkRequest::Timings::connect
std::chrono::microseconds connect
Definition request.h:80
PathInfo.h
ZYPP_IMPL_PRIVATE
#define ZYPP_IMPL_PRIVATE(Class)
Definition zyppglobal.h:85
Z_D
#define Z_D()
Definition zyppglobal.h:98