2828
2929#include < boost/throw_exception.hpp>
3030
31- // dependent libraries
32- #include < curl/curl.h>
33-
3431#include < algorithm>
3532#include < cassert>
3633#include < cstring>
@@ -68,6 +65,7 @@ struct CurlAgent::Impl
6865 std::string error_headers ;
6966 std::string error_data ;
7067 DataStream *dest ;
68+ u64_t total_download, total_upload ;
7169} ;
7270
7371static struct curl_slist * SetHeader ( CURL * handle, const Header& hdr );
@@ -94,6 +92,7 @@ void CurlAgent::Init()
9492 m_pimpl->error_headers = " " ;
9593 m_pimpl->error_data = " " ;
9694 m_pimpl->dest = NULL ;
95+ m_pimpl->total_download = m_pimpl->total_upload = 0 ;
9796}
9897
9998CurlAgent::~CurlAgent ()
@@ -111,6 +110,11 @@ void CurlAgent::SetLog(ResponseLog *log)
111110 m_log.reset ( log );
112111}
113112
113+ void CurlAgent::SetProgressReporter (Progress *progress)
114+ {
115+ m_pb = progress;
116+ }
117+
114118std::size_t CurlAgent::HeaderCallback ( void *ptr, size_t size, size_t nmemb, CurlAgent *pthis )
115119{
116120 char *str = static_cast <char *>(ptr) ;
@@ -131,7 +135,7 @@ std::size_t CurlAgent::HeaderCallback( void *ptr, size_t size, size_t nmemb, Cur
131135 if ( pos != line.npos )
132136 {
133137 std::size_t end_pos = line.find ( " \r\n " , pos ) ;
134- pthis->m_pimpl ->location = line.substr ( loc.size (), end_pos - loc.size () ) ;
138+ pthis->m_pimpl ->location = line.substr ( pos+ loc.size (), end_pos - loc.size () ) ;
135139 }
136140
137141 return size*nmemb ;
@@ -142,6 +146,7 @@ std::size_t CurlAgent::Receive( void* ptr, size_t size, size_t nmemb, CurlAgent
142146 assert ( pthis != 0 ) ;
143147 if ( pthis->m_log .get () )
144148 pthis->m_log ->Write ( (const char *)ptr, size*nmemb );
149+
145150 if ( pthis->m_pimpl ->error && pthis->m_pimpl ->error_data .size () < 65536 )
146151 {
147152 // Do not feed error responses to destination stream
@@ -151,6 +156,19 @@ std::size_t CurlAgent::Receive( void* ptr, size_t size, size_t nmemb, CurlAgent
151156 return pthis->m_pimpl ->dest ->Write ( static_cast <char *>(ptr), size * nmemb ) ;
152157}
153158
159+ int CurlAgent::progress_callback ( CurlAgent *pthis, curl_off_t totalDownload, curl_off_t finishedDownload, curl_off_t totalUpload, curl_off_t finishedUpload )
160+ {
161+ // Only report download progress when set explicitly
162+ totalDownload = pthis->m_pimpl ->total_download ;
163+ if ( !totalUpload )
164+ totalUpload = pthis->m_pimpl ->total_upload ;
165+ pthis->m_pb ->reportProgress (
166+ totalDownload > 0 ? totalDownload : totalUpload,
167+ totalDownload > 0 ? finishedDownload : finishedUpload
168+ );
169+ return 0 ;
170+ }
171+
154172long CurlAgent::ExecCurl (
155173 const std::string& url,
156174 DataStream *dest,
@@ -168,6 +186,10 @@ long CurlAgent::ExecCurl(
168186
169187 struct curl_slist *slist = SetHeader ( m_pimpl->curl , hdr ) ;
170188
189+ curl_easy_setopt (curl, CURLOPT_NOPROGRESS , 0L );
190+ curl_easy_setopt (curl, CURLOPT_XFERINFOFUNCTION , progress_callback);
191+ curl_easy_setopt (curl, CURLOPT_XFERINFODATA , this );
192+
171193 CURLcode curl_code = ::curl_easy_perform (curl);
172194
173195 curl_slist_free_all (slist);
@@ -202,11 +224,13 @@ long CurlAgent::Request(
202224 const std::string& url,
203225 SeekStream *in,
204226 DataStream *dest,
205- const Header& hdr )
227+ const Header& hdr,
228+ u64_t downloadFileBytes )
206229{
207230 Trace (" HTTP %1% \" %2%\" " , method, url ) ;
208231
209232 Init () ;
233+ m_pimpl->total_download = downloadFileBytes ;
210234 CURL *curl = m_pimpl->curl ;
211235
212236 // set common options
0 commit comments