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 #include "request_tracer.h"
24 #include "trace_events.h"
25 #include "http_client.h"
26 #include "netstack_log.h"
27 #ifdef HTTP_HANDOVER_FEATURE
28 #include "http_handover_info.h"
29 #endif
30
31 namespace OHOS {
32 namespace NetStack {
33 namespace HttpClient {
34 class HttpGlobal {
35 public:
HttpGlobal()36 HttpGlobal()
37 {
38 if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
39 NETSTACK_LOGE("Failed to initialize 'curl'");
40 }
41 }
~HttpGlobal()42 ~HttpGlobal()
43 {
44 NETSTACK_LOGD("Deinit curl_global_cleanup()");
45 curl_global_cleanup();
46 }
47 };
48 static HttpGlobal g_httpGlobal;
49
50 HttpSession::HttpSession() = default;
51
~HttpSession()52 HttpSession::~HttpSession()
53 {
54 NETSTACK_LOGD("~HttpSession::enter");
55 }
56
GetInstance()57 HttpSession &HttpSession::GetInstance()
58 {
59 static HttpSession gInstance;
60 return gInstance;
61 }
62
CreateTask(const HttpClientRequest & request)63 std::shared_ptr<HttpClientTask> HttpSession::CreateTask(const HttpClientRequest &request)
64 {
65 std::shared_ptr<HttpClientTask> ptr = std::make_shared<HttpClientTask>(request);
66 if (ptr->GetCurlHandle() == nullptr) {
67 NETSTACK_LOGE("CreateTask A error!");
68 return nullptr;
69 }
70
71 return ptr;
72 }
73
CreateTask(const HttpClientRequest & request,TaskType type,const std::string & filePath)74 std::shared_ptr<HttpClientTask> HttpSession::CreateTask(const HttpClientRequest &request, TaskType type,
75 const std::string &filePath)
76 {
77 std::shared_ptr<HttpClientTask> ptr = std::make_shared<HttpClientTask>(request, type, filePath);
78 if (ptr->GetCurlHandle() == nullptr) {
79 NETSTACK_LOGE("CreateTask B error!");
80 return nullptr;
81 }
82 return ptr;
83 }
84
SetRequestInfoCallbacks(HttpOverCurl::TransferCallbacks & callbacks,const std::shared_ptr<HttpClientTask> & ptr)85 void HttpSession::SetRequestInfoCallbacks(
86 HttpOverCurl::TransferCallbacks &callbacks, const std::shared_ptr<HttpClientTask> &ptr)
87 {
88 if (nullptr == ptr) {
89 return;
90 }
91 auto startedCallback = [ptr](CURL *, void *) {
92 ptr->GetTrace().Tracepoint(TraceEvents::QUEUE);
93 };
94 auto responseCallback = [ptr](CURLMsg *curlMessage, void *) {
95 ptr->GetTrace().Tracepoint(TraceEvents::NATIVE);
96 ptr->ProcessResponse(curlMessage);
97 ptr->SetStatus(TaskStatus::IDLE);
98 };
99 callbacks.startedCallback = startedCallback;
100 callbacks.doneCallback = responseCallback;
101
102 #ifdef HTTP_HANDOVER_FEATURE
103 auto handoverInfoCallback = [ptr](void *) {
104 HttpHandoverStackInfo httpHandoverStackInfo;
105 httpHandoverStackInfo.taskId = ptr->GetTaskId();
106 httpHandoverStackInfo.readTimeout = ptr->GetRequest().GetTimeout();
107 httpHandoverStackInfo.connectTimeout = ptr->GetRequest().GetConnectTimeout();
108 httpHandoverStackInfo.method = ptr->GetRequest().GetMethod();
109 httpHandoverStackInfo.requestUrl = ptr->GetRequest().GetURL();
110 httpHandoverStackInfo.isInStream = ptr->onDataReceive_ ? true : false;
111 httpHandoverStackInfo.isSuccess = ptr->IsSuccess();
112 return httpHandoverStackInfo;
113 };
114 static auto setHandoverInfoCallback = [ptr](HttpHandoverInfo httpHandoverInfo, void *) {
115 ptr->SetRequestHandoverInfo(httpHandoverInfo.handoverNum,
116 httpHandoverInfo.handoverReason,
117 httpHandoverInfo.flowControlTime,
118 httpHandoverInfo.readFlag);
119 };
120 callbacks.handoverInfoCallback = handoverInfoCallback;
121 callbacks.setHandoverInfoCallback = setHandoverInfoCallback;
122 #endif
123 }
124
StartTask(const std::shared_ptr<HttpClientTask> & ptr)125 void HttpSession::StartTask(const std::shared_ptr<HttpClientTask> &ptr)
126 {
127 if (nullptr == ptr) {
128 NETSTACK_LOGE("HttpSession::StartTask shared_ptr = nullptr! Error!");
129 return;
130 }
131
132 static HttpOverCurl::EpollRequestHandler requestHandler;
133
134 ptr->SetStatus(TaskStatus::RUNNING);
135
136 HttpOverCurl::TransferCallbacks callbacks;
137 SetRequestInfoCallbacks(callbacks, ptr);
138 #ifdef HTTP_HANDOVER_FEATURE
139 requestHandler.Process(ptr->GetCurlHandle(), callbacks, &ptr->GetRequest());
140 #else
141 requestHandler.Process(ptr->GetCurlHandle(), callbacks);
142 #endif
143 }
144
145 } // namespace HttpClient
146 } // namespace NetStack
147 } // namespace OHOS
148