1 /*
2 * Copyright (c) 2023-2024 Huawei Device Co., Ltd.
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 * http://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
16 #include <atomic>
17 #include <curl/curl.h>
18 #include <functional>
19 #include <iostream>
20 #include <sstream>
21
22 #include "epoll_request_handler.h"
23 #if !defined(_WIN32) && !defined(__APPLE__)
24 #include "hitrace_meter.h"
25 #endif
26 #include "http_client.h"
27 #include "netstack_log.h"
28
29 namespace OHOS {
30 namespace NetStack {
31 namespace HttpClient {
32 #if !defined(_WIN32) && !defined(__APPLE__)
33 static constexpr const char *HTTP_REQ_TRACE_NAME = "HttpRequestInner";
34 #endif
35
36 class HttpGlobal {
37 public:
HttpGlobal()38 HttpGlobal()
39 {
40 if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
41 NETSTACK_LOGE("Failed to initialize 'curl'");
42 }
43 }
~HttpGlobal()44 ~HttpGlobal()
45 {
46 NETSTACK_LOGD("Deinit curl_global_cleanup()");
47 curl_global_cleanup();
48 }
49 };
50 static HttpGlobal g_httpGlobal;
51
52 HttpSession::HttpSession() = default;
53
~HttpSession()54 HttpSession::~HttpSession()
55 {
56 NETSTACK_LOGD("~HttpSession::enter");
57 }
58
GetInstance()59 HttpSession &HttpSession::GetInstance()
60 {
61 static HttpSession gInstance;
62 return gInstance;
63 }
64
CreateTask(const HttpClientRequest & request)65 std::shared_ptr<HttpClientTask> HttpSession::CreateTask(const HttpClientRequest &request)
66 {
67 std::shared_ptr<HttpClientTask> ptr = std::make_shared<HttpClientTask>(request);
68 if (ptr->GetCurlHandle() == nullptr) {
69 NETSTACK_LOGE("CreateTask A error!");
70 return nullptr;
71 }
72
73 return ptr;
74 }
75
CreateTask(const HttpClientRequest & request,TaskType type,const std::string & filePath)76 std::shared_ptr<HttpClientTask> HttpSession::CreateTask(const HttpClientRequest &request, TaskType type,
77 const std::string &filePath)
78 {
79 std::shared_ptr<HttpClientTask> ptr = std::make_shared<HttpClientTask>(request, type, filePath);
80 if (ptr->GetCurlHandle() == nullptr) {
81 NETSTACK_LOGE("CreateTask B error!");
82 return nullptr;
83 }
84 return ptr;
85 }
86
StartTask(const std::shared_ptr<HttpClientTask> & ptr)87 void HttpSession::StartTask(const std::shared_ptr<HttpClientTask> &ptr)
88 {
89 if (nullptr == ptr) {
90 NETSTACK_LOGE("HttpSession::StartTask shared_ptr = nullptr! Error!");
91 return;
92 }
93
94 static HttpOverCurl::EpollRequestHandler requestHandler;
95
96 ptr->SetStatus(TaskStatus::RUNNING);
97
98 auto startedCallback = [ptr](CURL *, void *) {};
99 #if !defined(_WIN32) && !defined(__APPLE__)
100 std::stringstream name;
101 name << HTTP_REQ_TRACE_NAME << "_" << std::this_thread::get_id();
102 std::string traceName = name.str();
103 StartAsyncTrace(HITRACE_TAG_NET, traceName, ptr->GetTaskId());
104
105 auto responseCallback = [ptr, traceName](CURLMsg *curlMessage, void *) {
106 FinishAsyncTrace(HITRACE_TAG_NET, traceName, ptr->GetTaskId());
107 ptr->ProcessResponse(curlMessage);
108 ptr->SetStatus(TaskStatus::IDLE);
109 };
110 #else
111 auto responseCallback = [ptr](CURLMsg *curlMessage, void *) {
112 ptr->ProcessResponse(curlMessage);
113 ptr->SetStatus(TaskStatus::IDLE);
114 };
115 #endif
116 requestHandler.Process(ptr->GetCurlHandle(), startedCallback, responseCallback);
117 }
118
119 } // namespace HttpClient
120 } // namespace NetStack
121 } // namespace OHOS
122