libzypp 17.37.10

curlmultiparthandler.h
Go to the documentation of this file.
1#ifndef ZYPPNG_CURLMULTIPARTHANDLER_H
2#define ZYPPNG_CURLMULTIPARTHANDLER_H
3
4#include <zypp-core/zyppng/base/Base>
5#include <zypp-core/zyppng/core/ByteArray>
6#include <zypp-core/Digest.h>
7#include <zypp-core/zyppng/pipelines/Expected>
8#include <zypp-curl/ng/network/NetworkRequestError>
9#include <zypp-curl/ng/network/rangedesc.h>
10
11#include <optional>
12#include <any>
13
14 namespace zyppng {
15
19 class CurlMultiPartDataReceiver {
20 public:
21 virtual ~CurlMultiPartDataReceiver() = default;
22
26 virtual size_t headerfunction ( char *ptr, size_t bytes ) = 0;
27
33 virtual size_t writefunction ( char *ptr, std::optional<off_t> offset, size_t bytes ) = 0;
34
42 virtual bool beginRange ( off_t range, std::string &cancelReason ) { return true; };
43
54 virtual bool finishedRange ( off_t range, bool validated, std::string &cancelReason ) { return true; };
55
59 virtual void notifyErrorCodeChanged () {};
60 };
61
69 class CurlMultiPartHandler : public Base
70 {
71 public:
72
73 enum class ProtocolMode{
74 Basic, //< use this mode if no special checks are required in header or write callbacks
75 HTTP //< this mode is used for HTTP and HTTPS downloads
76 };
77
78 // when requesting ranges from the server, we need to make sure not to request
79 // too many at the same time. Instead we batch our requests and reuse the open
80 // connection until we have the full file.
81 // However different server have different maximum nr of ranges, so we start with
82 // a high number and decrease until we find a rangecount that works
83 constexpr static unsigned _rangeAttempt[] = {
84 255,
85 127,
86 63,
87 15,
88 5,
89 1
90 };
91
92 constexpr static unsigned _rangeAttemptSize = ( sizeof( _rangeAttempt ) / sizeof(unsigned) );
93
94 enum State {
95 Pending, //< waiting to be dispatched
96 Running, //< currently running
97 Finished, //< finished successfully
98 Error, //< Error, use error function to figure out the issue
99 };
100
101 using CheckSumBytes = UByteArray;
102 using Code = NetworkRequestError::Type;
103
104 struct Range : public RangeDesc {
105
106 Range( ) = default;
107 Range( RangeDesc &&rd, std::optional<zypp::Digest> dig, std::any userD, State rangeState = State::Pending );
108
109 size_t bytesWritten = 0;
110
114 std::optional<zypp::Digest> _digest = {}; //< zypp::Digest that is updated when data is written, can be used to validate the file contents with a checksum
115
116 std::any userData; //< Custom data the user can associate with the Range
117
118 State _rangeState = State::Pending; //< Flag to know if this range has been already requested and if the request was successful
119
120 void restart();
121 Range clone() const;
122
123 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 = {} );
124 };
125
126 CurlMultiPartHandler( ProtocolMode mode, void *easyHandle, std::vector<Range> &ranges, CurlMultiPartDataReceiver &receiver );
127 ~CurlMultiPartHandler() override;
128
129 void *easyHandle() const;
130 bool canRecover() const;
131 bool hasMoreWork() const;
132
133 bool hasError() const;
134
135 Code lastError() const;
136 const std::string &lastErrorMessage() const;
137
138 bool validateRange(Range &rng);
139
140 bool prepare( );
141 bool prepareToContinue( );
142 void finalize( );
143
144 bool verifyData( );
145
146 std::optional<size_t> reportedFileSize() const;
147 std::optional<off_t> currentRange() const;
148
149 private:
150
151 void setCode ( Code c, std::string msg, bool force = false );
152
153 static size_t curl_hdrcallback ( char *ptr, size_t size, size_t nmemb, void *userdata );
154 static size_t curl_wrtcallback ( char *ptr, size_t size, size_t nmemb, void *userdata );
155
156 size_t hdrcallback ( char *ptr, size_t size, size_t nmemb );
157 size_t wrtcallback ( char *ptr, size_t size, size_t nmemb );
158 bool parseContentRangeHeader(const std::string_view &line, size_t &start, size_t &len, size_t &fileLen);
159 bool parseContentTypeMultiRangeHeader(const std::string_view &line, std::string &boundary);
160 bool checkIfRangeChkSumIsValid( Range &rng );
161 void setRangeState ( Range &rng, State state );
162
163 ProtocolMode _protocolMode = ProtocolMode::HTTP;
164 void *_easyHandle = nullptr;
165 CurlMultiPartDataReceiver &_receiver;
166
167 Code _lastCode = Code::NoError;
168 std::string _lastErrorMsg;
169
170 bool _allHeadersReceived = false; //< set to true once writefunc was called once e.g. all headers have been received
171 bool _gotContentRangeInfo = false; //< Set to true if the server indicates ranges
172 bool _isMuliPartResponse = false; //< Set to true if the respone is in multipart form
173
174 std::string _seperatorString;
175 std::vector<char> _rangePrefaceBuffer;
176
177 std::optional<off_t> _currentRange;
178 std::optional<Range> _currentSrvRange;
179 std::optional<size_t> _reportedFileSize;
180
181 unsigned _rangeAttemptIdx = 0;
182 std::vector<Range> &_requestedRanges;
183 };
184
185} // namespace zyppng
186
187#endif // ZYPPNG_CURLMULTIPARTHANDLER_H
zypp::UByteArray
Definition ByteArray.h:46
zyppng::Base::Base
Base()
Definition base.cc:20
zyppng::CurlMultiPartDataReceiver
Definition curlmultiparthandler.h:19
zyppng::CurlMultiPartDataReceiver::headerfunction
virtual size_t headerfunction(char *ptr, size_t bytes)=0
zyppng::CurlMultiPartDataReceiver::notifyErrorCodeChanged
virtual void notifyErrorCodeChanged()
Definition curlmultiparthandler.h:59
zyppng::CurlMultiPartDataReceiver::~CurlMultiPartDataReceiver
virtual ~CurlMultiPartDataReceiver()=default
zyppng::CurlMultiPartDataReceiver::writefunction
virtual size_t writefunction(char *ptr, std::optional< off_t > offset, size_t bytes)=0
zyppng::CurlMultiPartDataReceiver::finishedRange
virtual bool finishedRange(off_t range, bool validated, std::string &cancelReason)
Definition curlmultiparthandler.h:54
zyppng::CurlMultiPartDataReceiver::beginRange
virtual bool beginRange(off_t range, std::string &cancelReason)
Definition curlmultiparthandler.h:42
zyppng::CurlMultiPartHandler::prepare
bool prepare()
Definition curlmultiparthandler.cc:522
zyppng::CurlMultiPartHandler::lastError
Code lastError() const
Definition curlmultiparthandler.cc:461
zyppng::CurlMultiPartHandler::wrtcallback
size_t wrtcallback(char *ptr, size_t size, size_t nmemb)
Definition curlmultiparthandler.cc:204
zyppng::CurlMultiPartHandler::_rangeAttemptIdx
unsigned _rangeAttemptIdx
Definition curlmultiparthandler.h:181
zyppng::CurlMultiPartHandler::_rangeAttemptSize
static constexpr unsigned _rangeAttemptSize
Definition curlmultiparthandler.h:92
zyppng::CurlMultiPartHandler::_protocolMode
ProtocolMode _protocolMode
Definition curlmultiparthandler.h:163
zyppng::CurlMultiPartHandler::CurlMultiPartHandler
CurlMultiPartHandler(ProtocolMode mode, void *easyHandle, std::vector< Range > &ranges, CurlMultiPartDataReceiver &receiver)
Definition curlmultiparthandler.cc:102
zyppng::CurlMultiPartHandler::finalize
void finalize()
Definition curlmultiparthandler.cc:490
zyppng::CurlMultiPartHandler::_lastCode
Code _lastCode
Definition curlmultiparthandler.h:167
zyppng::CurlMultiPartHandler::_currentSrvRange
std::optional< Range > _currentSrvRange
Definition curlmultiparthandler.h:178
zyppng::CurlMultiPartHandler::_seperatorString
std::string _seperatorString
The seperator string for multipart responses as defined in RFC 7233 Section 4.1.
Definition curlmultiparthandler.h:174
zyppng::CurlMultiPartHandler::canRecover
bool canRecover() const
Definition curlmultiparthandler.cc:440
zyppng::CurlMultiPartHandler::prepareToContinue
bool prepareToContinue()
Definition curlmultiparthandler.cc:471
zyppng::CurlMultiPartHandler::Code
NetworkRequestError::Type Code
Definition curlmultiparthandler.h:102
zyppng::CurlMultiPartHandler::_isMuliPartResponse
bool _isMuliPartResponse
Definition curlmultiparthandler.h:172
zyppng::CurlMultiPartHandler::_lastErrorMsg
std::string _lastErrorMsg
Definition curlmultiparthandler.h:168
zyppng::CurlMultiPartHandler::_gotContentRangeInfo
bool _gotContentRangeInfo
Definition curlmultiparthandler.h:171
zyppng::CurlMultiPartHandler::curl_wrtcallback
static size_t curl_wrtcallback(char *ptr, size_t size, size_t nmemb, void *userdata)
Definition curlmultiparthandler.cc:44
zyppng::CurlMultiPartHandler::curl_hdrcallback
static size_t curl_hdrcallback(char *ptr, size_t size, size_t nmemb, void *userdata)
Definition curlmultiparthandler.cc:35
zyppng::CurlMultiPartHandler::~CurlMultiPartHandler
~CurlMultiPartHandler() override
Definition curlmultiparthandler.cc:115
zyppng::CurlMultiPartHandler::lastErrorMessage
const std::string & lastErrorMessage() const
Definition curlmultiparthandler.cc:466
zyppng::CurlMultiPartHandler::_rangeAttempt
static constexpr unsigned _rangeAttempt[]
Definition curlmultiparthandler.h:83
zyppng::CurlMultiPartHandler::parseContentRangeHeader
bool parseContentRangeHeader(const std::string_view &line, size_t &start, size_t &len, size_t &fileLen)
Definition curlmultiparthandler.cc:654
zyppng::CurlMultiPartHandler::setCode
void setCode(Code c, std::string msg, bool force=false)
Definition curlmultiparthandler.cc:643
zyppng::CurlMultiPartHandler::_rangePrefaceBuffer
std::vector< char > _rangePrefaceBuffer
Here we buffer.
Definition curlmultiparthandler.h:175
zyppng::CurlMultiPartHandler::currentRange
std::optional< off_t > currentRange() const
Definition curlmultiparthandler.cc:730
zyppng::CurlMultiPartHandler::_reportedFileSize
std::optional< size_t > _reportedFileSize
Filesize as reported by the content range or byte range headers.
Definition curlmultiparthandler.h:179
zyppng::CurlMultiPartHandler::hdrcallback
size_t hdrcallback(char *ptr, size_t size, size_t nmemb)
Definition curlmultiparthandler.cc:125
zyppng::CurlMultiPartHandler::validateRange
bool validateRange(Range &rng)
Definition curlmultiparthandler.cc:687
zyppng::CurlMultiPartHandler::State
State
Definition curlmultiparthandler.h:94
zyppng::CurlMultiPartHandler::Running
@ Running
Definition curlmultiparthandler.h:96
zyppng::CurlMultiPartHandler::Error
@ Error
Definition curlmultiparthandler.h:98
zyppng::CurlMultiPartHandler::Pending
@ Pending
Definition curlmultiparthandler.h:95
zyppng::CurlMultiPartHandler::Finished
@ Finished
Definition curlmultiparthandler.h:97
zyppng::CurlMultiPartHandler::_receiver
CurlMultiPartDataReceiver & _receiver
Definition curlmultiparthandler.h:165
zyppng::CurlMultiPartHandler::hasMoreWork
bool hasMoreWork() const
Definition curlmultiparthandler.cc:450
zyppng::CurlMultiPartHandler::hasError
bool hasError() const
Definition curlmultiparthandler.cc:456
zyppng::CurlMultiPartHandler::setRangeState
void setRangeState(Range &rng, State state)
Definition curlmultiparthandler.cc:723
zyppng::CurlMultiPartHandler::reportedFileSize
std::optional< size_t > reportedFileSize() const
Definition curlmultiparthandler.cc:735
zyppng::CurlMultiPartHandler::parseContentTypeMultiRangeHeader
bool parseContentTypeMultiRangeHeader(const std::string_view &line, std::string &boundary)
Definition curlmultiparthandler.cc:673
zyppng::CurlMultiPartHandler::_easyHandle
void * _easyHandle
Definition curlmultiparthandler.h:164
zyppng::CurlMultiPartHandler::_allHeadersReceived
bool _allHeadersReceived
Definition curlmultiparthandler.h:170
zyppng::CurlMultiPartHandler::easyHandle
void * easyHandle() const
Definition curlmultiparthandler.cc:435
zyppng::CurlMultiPartHandler::checkIfRangeChkSumIsValid
bool checkIfRangeChkSumIsValid(Range &rng)
Definition curlmultiparthandler.cc:703
zyppng::CurlMultiPartHandler::ProtocolMode
ProtocolMode
Definition curlmultiparthandler.h:73
zyppng::CurlMultiPartHandler::ProtocolMode::HTTP
@ HTTP
Definition curlmultiparthandler.h:75
zyppng::CurlMultiPartHandler::ProtocolMode::Basic
@ Basic
Definition curlmultiparthandler.h:74
zyppng::CurlMultiPartHandler::_requestedRanges
std::vector< Range > & _requestedRanges
the requested ranges that need to be downloaded
Definition curlmultiparthandler.h:182
zyppng::CurlMultiPartHandler::CheckSumBytes
UByteArray CheckSumBytes
Definition curlmultiparthandler.h:101
zyppng::CurlMultiPartHandler::verifyData
bool verifyData()
Definition curlmultiparthandler.cc:502
zyppng::CurlMultiPartHandler::_currentRange
std::optional< off_t > _currentRange
Definition curlmultiparthandler.h:177
zyppng::NetworkRequestError::Type
Type
Definition networkrequesterror.h:26
zyppng
Definition MediaNetworkRequestExecutor.h:16
rangedesc.h
zyppng::CurlMultiPartHandler::Range
Definition curlmultiparthandler.h:104
zyppng::CurlMultiPartHandler::Range::_rangeState
State _rangeState
Definition curlmultiparthandler.h:118
zyppng::CurlMultiPartHandler::Range::_digest
std::optional< zypp::Digest > _digest
Enables automated checking of downloaded contents against a checksum.
Definition curlmultiparthandler.h:114
zyppng::CurlMultiPartHandler::Range::clone
Range clone() const
Definition curlmultiparthandler.cc:67
zyppng::CurlMultiPartHandler::Range::Range
Range()=default
zyppng::CurlMultiPartHandler::Range::bytesWritten
size_t bytesWritten
Definition curlmultiparthandler.h:109
zyppng::CurlMultiPartHandler::Range::restart
void restart()
Definition curlmultiparthandler.cc:60
zyppng::CurlMultiPartHandler::Range::userData
std::any userData
Definition curlmultiparthandler.h:116
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::RangeDesc
Definition rangedesc.h:27
Digest.h