xref: /aosp_15_r20/external/federated-compute/fcp/client/http/curl/curl_http_request_handle.h (revision 14675a029014e728ec732f129a32e299b2da0601)
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