xref: /aosp_15_r20/external/sandboxed-api/oss-internship-2020/curl/examples/example4.cc (revision ec63e07ab9515d95e79c211197c445ef84cefa6a)
1 // Copyright 2020 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 // Sandboxed version of multi-poll.c
16 // HTTP GET request with polling
17 
18 #include <cstdlib>
19 
20 #include "../curl_util.h"    // NOLINT(build/include)
21 #include "../sandbox.h"      // NOLINT(build/include)
22 #include "curl_sapi.sapi.h"  // NOLINT(build/include)
23 #include "absl/strings/str_cat.h"
24 #include "sandboxed_api/util/status_macros.h"
25 
26 namespace {
27 
Example4()28 absl::Status Example4() {
29   // Initialize sandbox2 and sapi
30   curl::CurlSapiSandbox sandbox;
31   SAPI_RETURN_IF_ERROR(sandbox.Init());
32   curl::CurlApi api(&sandbox);
33 
34   // Number of running handles
35   sapi::v::Int still_running(1);
36 
37   int curl_code;
38 
39   // Initialize curl (CURL_GLOBAL_DEFAULT = 3)
40   SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_global_init(3l));
41   if (curl_code != 0) {
42     return absl::UnavailableError(absl::StrCat(
43         "curl_global_init failed: ", curl::StrError(&api, curl_code)));
44   }
45 
46   // Initialize http_handle
47   curl::CURL* curl_handle;
48   SAPI_ASSIGN_OR_RETURN(curl_handle, api.curl_easy_init());
49   sapi::v::RemotePtr http_handle(curl_handle);
50   if (!curl_handle) {
51     return absl::UnavailableError("curl_easy_init failed: Invalid curl handle");
52   }
53 
54   // Specify URL to get
55   sapi::v::ConstCStr url("http://example.com");
56   SAPI_ASSIGN_OR_RETURN(
57       curl_code, api.curl_easy_setopt_ptr(&http_handle, curl::CURLOPT_URL,
58                                           url.PtrBefore()));
59   if (curl_code != 0) {
60     return absl::UnavailableError(absl::StrCat(
61         "curl_easy_setopt_ptr failed: ", curl::StrError(&api, curl_code)));
62   }
63 
64   // Initialize multi_handle
65   curl::CURLM* curlm_handle;
66   SAPI_ASSIGN_OR_RETURN(curlm_handle, api.curl_multi_init());
67   sapi::v::RemotePtr multi_handle(curlm_handle);
68   if (!curlm_handle) {
69     return absl::UnavailableError(
70         "curl_multi_init failed: multi_handle is invalid");
71   }
72 
73   // Add http_handle to the multi stack
74   SAPI_ASSIGN_OR_RETURN(curl_code,
75                         api.curl_multi_add_handle(&multi_handle, &http_handle));
76   if (curl_code != 0) {
77     return absl::UnavailableError(absl::StrCat(
78         "curl_multi_add_handle failed: ", curl::StrError(&api, curl_code)));
79   }
80 
81   while (still_running.GetValue()) {
82     sapi::v::Int numfds(0);
83 
84     // Perform the request
85     SAPI_ASSIGN_OR_RETURN(
86         curl_code,
87         api.curl_multi_perform(&multi_handle, still_running.PtrBoth()));
88     if (curl_code != 0) {
89       return absl::UnavailableError(absl::StrCat(
90           "curl_mutli_perform failed: ", curl::StrError(&api, curl_code)));
91     }
92 
93     if (still_running.GetValue()) {
94       // Wait for an event or timeout
95       sapi::v::NullPtr null_ptr;
96       SAPI_ASSIGN_OR_RETURN(
97           curl_code, api.curl_multi_poll_sapi(&multi_handle, &null_ptr, 0, 1000,
98                                               numfds.PtrBoth()));
99       if (curl_code != 0) {
100         return absl::UnavailableError(absl::StrCat(
101             "curl_multi_poll_sapi failed: ", curl::StrError(&api, curl_code)));
102       }
103     }
104   }
105 
106   // Remove http_handle from the multi stack
107   SAPI_ASSIGN_OR_RETURN(
108       curl_code, api.curl_multi_remove_handle(&multi_handle, &http_handle));
109   if (curl_code != 0) {
110     return absl::UnavailableError(absl::StrCat(
111         "curl_multi_remove_handle failed: ", curl::StrError(&api, curl_code)));
112   }
113 
114   // Cleanup http_handle
115   SAPI_RETURN_IF_ERROR(api.curl_easy_cleanup(&http_handle));
116 
117   // Cleanup multi_handle
118   SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_multi_cleanup(&multi_handle));
119   if (curl_code != 0) {
120     return absl::UnavailableError(absl::StrCat(
121         "curl_multi_cleanup failed: ", curl::StrError(&api, curl_code)));
122   }
123 
124   // Cleanup curl
125   SAPI_RETURN_IF_ERROR(api.curl_global_cleanup());
126 
127   return absl::OkStatus();
128 }
129 
130 }  // namespace
131 
main(int argc,char * argv[])132 int main(int argc, char* argv[]) {
133   gflags::ParseCommandLineFlags(&argc, &argv, true);
134   sapi::InitLogging(argv[0]);
135 
136   if (absl::Status status = Example4(); !status.ok()) {
137     LOG(ERROR) << "Example4 failed: " << status.ToString();
138     return EXIT_FAILURE;
139   }
140 
141   return EXIT_SUCCESS;
142 }
143