1 /* 2 * Copyright 2022 Google LLC 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef FCP_CLIENT_HTTP_CURL_CURL_HTTP_REQUEST_HANDLE_H_ 18 #define FCP_CLIENT_HTTP_CURL_CURL_HTTP_REQUEST_HANDLE_H_ 19 20 #include <memory> 21 #include <string> 22 23 #include "absl/synchronization/mutex.h" 24 #include "curl/curl.h" 25 #include "fcp/client/http/curl/curl_api.h" 26 #include "fcp/client/http/curl/curl_header_parser.h" 27 #include "fcp/client/http/http_client.h" 28 29 namespace fcp::client::http::curl { 30 31 // A thread-safe curl-based implementation. Designed to be used with 32 // CurlHttpClient. 33 class CurlHttpRequestHandle : public HttpRequestHandle { 34 public: 35 // If non-empty, `test_cert_path` specifies the path to the Certificate 36 // Authority (CA) bundle to use instead of the system defaults. 37 CurlHttpRequestHandle(std::unique_ptr<HttpRequest> request, 38 std::unique_ptr<CurlEasyHandle> easy_handle, 39 const std::string& test_cert_path); 40 ~CurlHttpRequestHandle() override; 41 CurlHttpRequestHandle(const CurlHttpRequestHandle&) = delete; 42 CurlHttpRequestHandle& operator=(const CurlHttpRequestHandle&) = delete; 43 44 // Adds this request to the corresponding multi-handle that can execute 45 // multiple requests in parallel. The corresponding callbacks will be 46 // called accordingly. 47 absl::Status AddToMulti(CurlMultiHandle* multi_handle, 48 HttpRequestCallback* callback) 49 ABSL_LOCKS_EXCLUDED(mutex_); 50 // Removes this request from the corresponding multi-handle. 51 void RemoveFromMulti(CurlMultiHandle* multi_handle) 52 ABSL_LOCKS_EXCLUDED(mutex_); 53 // Marks the request as completed which fires the OnComplete callback. 54 void MarkAsCompleted() ABSL_LOCKS_EXCLUDED(mutex_); 55 56 // HttpRequestHandle overrides: 57 ABSL_MUST_USE_RESULT HttpRequestHandle::SentReceivedBytes 58 TotalSentReceivedBytes() const override ABSL_LOCKS_EXCLUDED(mutex_); 59 void Cancel() override ABSL_LOCKS_EXCLUDED(mutex_); 60 61 private: 62 // Initializes the easy_handle_ in the constructor. 63 CURLcode InitializeConnection(const std::string& test_cert_path) 64 ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); 65 // Initializes headers from external_headers 66 CURLcode InitializeHeaders(const HeaderList& extra_headers, 67 HttpRequest::Method method) 68 ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); 69 // A helper function called _sequentially_ when a response header received. 70 static size_t HeaderCallback(char* buffer, size_t size, size_t n_items, 71 void* user_data) ABSL_NO_THREAD_SAFETY_ANALYSIS; 72 // A helper function called _sequentially_ when a chunk of a body received 73 static size_t DownloadCallback(void* body, size_t size, size_t nmemb, 74 void* user_data) 75 ABSL_NO_THREAD_SAFETY_ANALYSIS; 76 // A helper function called _sequentially_ to send a chunk of a body. 77 static size_t UploadCallback(char* buffer, size_t size, size_t num, 78 void* user_data) ABSL_NO_THREAD_SAFETY_ANALYSIS; 79 80 // Called periodically. Used to cancel the request. 81 static size_t ProgressCallback(void* user_data, curl_off_t dltotal, 82 curl_off_t dlnow, curl_off_t ultotal, 83 curl_off_t ulnow) ABSL_LOCKS_EXCLUDED(mutex_); 84 85 mutable absl::Mutex mutex_; 86 const std::unique_ptr<HttpRequest> request_ ABSL_GUARDED_BY(mutex_); 87 std::unique_ptr<HttpResponse> response_ ABSL_GUARDED_BY(mutex_); 88 const std::unique_ptr<CurlEasyHandle> easy_handle_ ABSL_GUARDED_BY(mutex_); 89 // Used only in the HeaderCallback sequentially. 90 CurlHeaderParser header_parser_{}; 91 // Owned by the caller. Initialized in AddToMulti and then read-only. 92 HttpRequestCallback* callback_ ABSL_GUARDED_BY(mutex_); 93 bool is_being_performed_ ABSL_GUARDED_BY(mutex_); 94 bool is_completed_ ABSL_GUARDED_BY(mutex_); 95 bool is_cancelled_ ABSL_GUARDED_BY(mutex_); ABSL_GUARDED_BY(mutex_)96 char error_buffer_[CURL_ERROR_SIZE] ABSL_GUARDED_BY(mutex_){}; 97 // Owned by the class. 98 curl_slist* header_list_; 99 }; 100 } // namespace fcp::client::http::curl 101 102 #endif // FCP_CLIENT_HTTP_CURL_CURL_HTTP_REQUEST_HANDLE_H_ 103