@@ -30,29 +30,54 @@ namespace internal {
3030CurlDownloadRequest::CurlDownloadRequest (std::size_t initial_buffer_size)
3131 : headers_(nullptr , &curl_slist_free_all),
3232 multi_ (nullptr , &curl_multi_cleanup),
33+ closing_(false ),
3334 curl_closed_(false ),
3435 initial_buffer_size_(initial_buffer_size) {
3536 buffer_.reserve (initial_buffer_size);
3637}
3738
39+ HttpResponse CurlDownloadRequest::Close () {
40+ // Set the the closing_ flag to trigger a return 0 from the next read
41+ // callback, see the comments in the header file for more details.
42+ closing_ = true ;
43+ // Block until that callback is made.
44+ Wait ([this ] { return curl_closed_; });
45+
46+ // Now remove the handle from the CURLM* interface and wait for the response.
47+ auto error = curl_multi_remove_handle (multi_.get (), handle_.handle_ .get ());
48+ RaiseOnError (__func__, error);
49+
50+ long http_code = handle_.GetResponseCode ();
51+ return HttpResponse{http_code, std::string{}, std::move (received_headers_)};
52+ }
53+
3854HttpResponse CurlDownloadRequest::GetMore (std::string& buffer) {
3955 handle_.FlushDebug (__func__);
40- GCP_LOG (DEBUG) << __func__ << " (), curl.size=" << buffer_.size ();
4156 Wait ([this ] {
4257 return curl_closed_ or buffer_.size () >= initial_buffer_size_;
4358 });
59+ GCP_LOG (DEBUG) << __func__ << " (), curl.size=" << buffer_.size ()
60+ << " , closing=" << closing_ << " , closed=" << curl_closed_;
4461 if (curl_closed_) {
4562 // Remove the handle from the CURLM* interface and wait for the response.
4663 auto error = curl_multi_remove_handle (multi_.get (), handle_.handle_ .get ());
4764 RaiseOnError (__func__, error);
4865
49- buffer.swap (buffer_);
66+ buffer_.swap (buffer);
67+ buffer_.clear ();
5068 long http_code = handle_.GetResponseCode ();
69+ GCP_LOG (DEBUG) << __func__ << " (), size=" << buffer.size ()
70+ << " , closing=" << closing_ << " , closed=" << curl_closed_
71+ << " , code=" << http_code;
5172 return HttpResponse{http_code, std::string{}, std::move (received_headers_)};
5273 }
5374 buffer_.swap (buffer);
75+ buffer_.clear ();
5476 buffer_.reserve (initial_buffer_size_);
5577 handle_.EasyPause (CURLPAUSE_RECV_CONT);
78+ GCP_LOG (DEBUG) << __func__ << " (), size=" << buffer.size ()
79+ << " , closing=" << closing_ << " , closed=" << curl_closed_
80+ << " , code=100" ;
5681 return HttpResponse{100 , {}, {}};
5782}
5883
@@ -91,11 +116,18 @@ std::size_t CurlDownloadRequest::WriteCallback(void* ptr, std::size_t size,
91116 handle_.FlushDebug (__func__);
92117 GCP_LOG (DEBUG) << __func__ << " () size=" << size << " , nmemb=" << nmemb
93118 << " , buffer.size=" << buffer_.size ();
94-
95- buffer_.append (static_cast <char const *>(ptr), size * nmemb);
96- if (buffer_.size () > 128 * 1024 ) {
119+ // This transfer is closing, just return zero, that will make libcurl finish
120+ // any pending work, and will return the handle_ pointer from
121+ // curl_multi_info_read() in PerformWork(). That is the point where
122+ // `curl_closed_` is set.
123+ if (closing_) {
124+ return 0 ;
125+ }
126+ if (buffer_.size () >= initial_buffer_size_) {
97127 return CURL_READFUNC_PAUSE;
98128 }
129+
130+ buffer_.append (static_cast <char const *>(ptr), size * nmemb);
99131 return size * nmemb;
100132}
101133
0 commit comments