From 3b59cf0967e994f8f67c8f51847de29f5117ec2f Mon Sep 17 00:00:00 2001 From: YangWeimin Date: Wed, 28 May 2025 20:24:17 +0800 Subject: [PATCH 1/6] add handover module Signed-off-by: YangWeimin --- frameworks/js/napi/http/BUILD.gn | 2 + .../js/napi/http/http_exec/src/http_exec.cpp | 57 +++ .../include/epoll_multi_driver.h | 16 +- .../include/epoll_request_handler.h | 15 +- .../include/http_handover_handler.h | 99 ++++ .../include/manual_reset_event.h | 11 +- utils/http_over_curl/include/request_info.h | 5 +- .../include/transfer_callbacks.h | 6 +- .../http_over_curl/src/epoll_multi_driver.cpp | 38 +- .../src/epoll_request_handler.cpp | 53 +++ .../src/http_handover_handler.cpp | 423 ++++++++++++++++++ 11 files changed, 718 insertions(+), 7 deletions(-) create mode 100644 utils/http_over_curl/include/http_handover_handler.h create mode 100644 utils/http_over_curl/src/http_handover_handler.cpp diff --git a/frameworks/js/napi/http/BUILD.gn b/frameworks/js/napi/http/BUILD.gn index dc9622fdd..f2d6da3d1 100644 --- a/frameworks/js/napi/http/BUILD.gn +++ b/frameworks/js/napi/http/BUILD.gn @@ -171,7 +171,9 @@ ohos_shared_library("http") { "$NETSTACK_DIR/utils/netstack_chr_client/src/netstack_chr_report.cpp", "$NETSTACK_DIR/utils/http_over_curl/src/epoll_multi_driver.cpp", "$NETSTACK_DIR/utils/http_over_curl/src/epoll_request_handler.cpp", + "$NETSTACK_DIR/utils/http_over_curl/src/http_handover_handler.cpp", ] + defines = [ "HTTP_HANDOVER_FEATURE" ] } else { defines = [ "HAS_NETMANAGER_BASE=0", diff --git a/frameworks/js/napi/http/http_exec/src/http_exec.cpp b/frameworks/js/napi/http/http_exec/src/http_exec.cpp index f0e966937..a1e64ba21 100755 --- a/frameworks/js/napi/http/http_exec/src/http_exec.cpp +++ b/frameworks/js/napi/http/http_exec/src/http_exec.cpp @@ -118,6 +118,9 @@ static constexpr const int SSL_CTX_EX_DATA_REQUEST_CONTEXT_INDEX = 1; static constexpr const char *HTTP_AF_ONLYV4 = "ONLY_V4"; static constexpr const char *HTTP_AF_ONLYV6 = "ONLY_V6"; +#ifdef HTTP_HANDOVER_FEATURE +static bool IsHandOverFeature = false; +#endif static void RequestContextDeleter(RequestContext *context) { @@ -280,6 +283,37 @@ bool HttpExec::AddCurlHandle(CURL *handle, RequestContext *context) #if HAS_NETMANAGER_BASE std::stringstream name; name << HTTP_REQ_TRACE_NAME << "_" << std::this_thread::get_id(); +#ifdef HTTP_HANDOVER_FEATURE + context->SetTraceName(name.str()); + StartAsyncTrace(HITRACE_TAG_NET, context->GetTraceName(), context->GetTaskId()); + SetServerSSLCertOption(handle, context); + + static HttpOverCurl::EpollRequestHandler requestHandler(5000, true); + + static auto startedCallback = +[](CURL *easyHandle, void *opaqueData) { + char *url = nullptr; + curl_easy_getinfo(easyHandle, CURLINFO_EFFECTIVE_URL, &url); + }; + + static auto responseCallback = +[](CURLMsg *curlMessage, void *opaqueData) { + auto context = static_cast(opaqueData); + HttpExec::HandleCurlData(curlMessage, context); + }; + + if (requestHandler.GetRequestHandOver()) { + IsHandOverFeature = true; + static auto handOverCallback = + +[](void *opaqueData, int32_t handOverNum, int32_t handOverReason, double flowControlTime, int32_t isRead) { + auto context = static_cast(opaqueData); + context->SetRequestHandOverInfo(handOverNum, handOverReason, flowControlTime, isRead); + }; + requestHandler.Process(handle, startedCallback, responseCallback, handOverCallback, context); + } else { + static auto defaultHandOverCallback = +[](void *opaqueData, int32_t handOverNum, int32_t handOverReason, + double flowControlTime, int32_t isRead) {}; + requestHandler.Process(handle, startedCallback, responseCallback, defaultHandOverCallback, context); + } +#else SetTraceOptions(handle, context); SetServerSSLCertOption(handle, context); @@ -299,6 +333,7 @@ bool HttpExec::AddCurlHandle(CURL *handle, RequestContext *context) }; requestHandler.Process(handle, startedCallback, responseCallback, context); +#endif return true; #else std::thread([context, handle] { @@ -487,6 +522,27 @@ void HttpExec::CacheCurlPerformanceTiming(CURL *handle, RequestContext *context) char *ip = nullptr; curl_easy_getinfo(handle, CURLINFO_PRIMARY_IP, &ip); int32_t errCode = context->IsExecOK() ? 0 : context->GetErrorCode(); +#ifdef HTTP_HANDOVER_FEATURE + auto requestHandOverInfo = context->GetRequestHandOverInfo(); + if (IsHandOverFeature && requestHandOverInfo.handOverNum > 0) { + NETSTACK_LOGI("taskid=%{public}d" + ", size:%{public}" CURL_FORMAT_CURL_OFF_T + ", dns:%{public}.3f, connect:%{public}.3f, tls:%{public}.3f, firstSend:%{public}.3f" + ", firstRecv:%{public}.3f, total:%{public}.3f, redirect:%{public}.3f" + ", errCode:%{public}d, RespCode:%{public}s, httpVer:%{public}s, method:%{public}s, osErr:%{public}ld" + ", handOverNum:%{public}d, handOverReason:%{public}s, %{public}s:%{public}.3f, isRead:%{public}s, " + "isStream:%{public}s", + context->GetTaskId(), size, dnsTime, connectTime == 0 ? 0 : connectTime - dnsTime, + tlsTime == 0 ? 0 : tlsTime - connectTime, + firstSendTime == 0 ? 0 : firstSendTime - std::max({dnsTime, connectTime, tlsTime}), + firstRecvTime == 0 ? 0 : firstRecvTime - firstSendTime, totalTime, redirectTime, errCode, + std::to_string(responseCode).c_str(), std::to_string(httpVer).c_str(), context->options.GetMethod().c_str(), + osErr, requestHandOverInfo.handOverNum, requestHandOverInfo.handOverReason ? "flowControl" : "retrans", + requestHandOverInfo.handOverReason ? "flowControlTime" : "retransTime", requestHandOverInfo.flowControlTime, + requestHandOverInfo.isRead == 1 ? "true" : requestHandOverInfo.isRead == 0 ? "false" : "unknown", + context->IsRequestStream() ? "true" : "false"); + } +#else NETSTACK_LOGI( "taskid=%{public}d" ", size:%{public}" CURL_FORMAT_CURL_OFF_T @@ -499,6 +555,7 @@ void HttpExec::CacheCurlPerformanceTiming(CURL *handle, RequestContext *context) firstRecvTime == 0 ? 0 : firstRecvTime - firstSendTime, totalTime, redirectTime, errCode, std::to_string(responseCode).c_str(), std::to_string(httpVer).c_str(), context->options.GetMethod().c_str(), osErr); +#endif #if HAS_NETMANAGER_BASE if (EventReport::GetInstance().IsValid()) { HttpPerfInfo httpPerfInfo; diff --git a/utils/http_over_curl/include/epoll_multi_driver.h b/utils/http_over_curl/include/epoll_multi_driver.h index b85ccd540..17bdc06e7 100644 --- a/utils/http_over_curl/include/epoll_multi_driver.h +++ b/utils/http_over_curl/include/epoll_multi_driver.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -24,6 +24,9 @@ #include "epoller.h" #include "thread_safe_storage.h" #include "timeout_timer.h" +#ifdef HTTP_HANDOVER_FEATURE +#include "http_handover_handler.h" +#endif namespace OHOS::NetStack::HttpOverCurl { @@ -33,6 +36,10 @@ class EpollMultiDriver { public: EpollMultiDriver() = delete; explicit EpollMultiDriver(const std::shared_ptr> &incomingQueue); +#ifdef HTTP_HANDOVER_FEATURE + EpollMultiDriver(const std::shared_ptr> &incomingQueue, + std::shared_ptr &netHandoverHandler); +#endif ~EpollMultiDriver(); void Step(int waitEventsTimeoutMs); @@ -59,13 +66,18 @@ private: void Initialize(); void IncomingRequestCallback(); - +#ifdef HTTP_HANDOVER_FEATURE + void HandOverRequestCallback(); +#endif std::shared_ptr> incomingQueue_; HttpOverCurl::Epoller poller_; HttpOverCurl::TimeoutTimer timeoutTimer_; CURLM *multi_ = nullptr; +#ifdef HTTP_HANDOVER_FEATURE + std::shared_ptr netHandoverHandler_; +#endif // Number of running handles int stillRunning = 0; diff --git a/utils/http_over_curl/include/epoll_request_handler.h b/utils/http_over_curl/include/epoll_request_handler.h index 94d40f342..3792c59c6 100644 --- a/utils/http_over_curl/include/epoll_request_handler.h +++ b/utils/http_over_curl/include/epoll_request_handler.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -38,11 +38,24 @@ public: void Process(CURL *easyHandle, const TransferStartedCallback &startedCallback, const TransferDoneCallback &responseCallback, void *opaqueData = nullptr); +#ifdef HTTP_HANDOVER_FEATURE + explicit EpollRequestHandler(int sleepTimeoutMs = 5000, bool netHandover = false); + + void Process(CURL *easyHandle, const TransferStartedCallback &startedCallback, + const TransferDoneCallback &responseCallback, const TransferHandOverCallback &handOverCallback, + void *opaqueData = nullptr); + + bool GetRequestHandOver(); +#endif + private: void WorkingThread(); std::atomic_bool stop_ = false; std::once_flag init_; int sleepTimeoutMs_; +#ifdef HTTP_HANDOVER_FEATURE + bool netHandover_; +#endif std::thread workThread_; std::shared_ptr> incomingQueue_; diff --git a/utils/http_over_curl/include/http_handover_handler.h b/utils/http_over_curl/include/http_handover_handler.h new file mode 100644 index 000000000..f3dcb7735 --- /dev/null +++ b/utils/http_over_curl/include/http_handover_handler.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef COMMUNICATIONNETSTACK_HTTP_HANDOVER_HANDLER_H +#define COMMUNICATIONNETSTACK_HTTP_HANDOVER_HANDLER_H + +#include +#include +#include +#include + +#include "curl/curl.h" + +#include "epoller.h" +#include "thread_safe_storage.h" +#include "timeout_timer.h" +#include "manual_reset_event.h" +#include "epoll_request_handler.h" +#include "request_info.h" +#include "request_context.h" + +namespace OHOS::NetStack::HttpOverCurl { + +struct RequestInfo; + +class HttpHandoverHandler { +public: + enum { INIT, START, CONTINUE, END, FATAL }; + explicit HttpHandoverHandler(); + ~HttpHandoverHandler(); + + bool InitSuccess(); + void HandOverQuery(int32_t &status, int32_t &netId); + bool CheckSocketOpentimeLessThanEndTime(curl_socket_t fd); + void SetSocketOpenTime(curl_socket_t fd); + void EraseFd(curl_socket_t fd); + void SetEndTime(); + bool RetransRequest(std::map &ongoingRequests, CURLM *multi, RequestInfo *request); + bool CheckRequestCanRetrans(RequestInfo *request); + bool TryFlowControl(RequestInfo* requestInfo); + void RetransFailedHandle(std::map &ongoingRequests, std::queue &retransfailed); + void HandOverRequestCallback(std::map &ongoingRequests, CURLM *multi); + + void RegisterForPolling(Epoller &poller) const; + bool IsItYours(FileDescriptor descriptor) const; + void Set(); + int32_t IsRequestRead(CURL *easyHandle); + int32_t IsRequestRead(CURL *easyHandle, time_t &recvtime, time_t &sendtime); + bool ProcessRequestErr(CURL *easyHandle, std::map &ongoingRequests, CURLM *multi, + RequestInfo *requestInfo, CURLMsg *msg); + void SetHandOverInfo(CURL *easyHandle, RequestInfo *requestInfo); + bool CheckRequestNetError(std::map &ongoingRequests, CURLM multi, + RequestInfo *requestInfo, CURLMsg *msg); + void AddRequest(void *userp, bool isHandOver, int32_t isRead); + void DelRequest(void *userp); + int32_t QueryRequest(void *userp, int32_t &handOverReason, double &flowControlTime, int32_t &isRead); + +private: + bool Initialize(); + void SetCallback(RequestInfo *request); + void *netHandoverHandler_ = nullptr; + void *httpHandOverManager_ = nullptr; + std::unique_ptr handOverEvent_; + typedef void *(*HTTP_HAND_OVER_INIT)(void *user, void (*HMS_NetworkBoost_HandoverEventCallback)(void *)); + typedef int32_t (*HTTP_HAND_OVER_UNINIT)(void *handle); + typedef void (*HTTP_HAND_OVER_QUERY)(void *handle, int32_t &status, int32_t &netId); + typedef void (*HTTP_HAND_OVER_ADD)(void *handle, void *userp, bool isHandOver, int32_t isRead); + typedef void (*HTTP_HAND_OVER_DEL)(void *handle, void *userp, bool isSuccess); + typedef int32_t (*HTTP_HAND_OVER_QUERY_REQUEST)(void *handle, void *userp, int32_t *handOverReason, + double *flowControlTime, int32_t *isRead); + HTTP_HAND_OVER_INIT httpHandOverInit_ = nullptr; + HTTP_HAND_OVER_UNINIT httpHandOverUninit_ = nullptr; + HTTP_HAND_OVER_QUERY httpHandOverQuery_ = nullptr; + HTTP_HAND_OVER_ADD httpHandOverAddRequest_ = nullptr; + HTTP_HAND_OVER_DEL httpHandOverDelRequest_ = nullptr; + HTTP_HAND_OVER_QUERY_REQUEST httphandOverQueryRequest_ = nullptr; + std::set handoverQueue_; + std::map socketopentime_; + std::map requestEndtime_; + bool initsuccess_; + int endTime_ = 0; + int retrans_ = 0; +}; + +} // namespace OHOS::NetStack::HttpOverCurl + +#endif // COMMUNICATIONNETSTACK_HTTP_HANOVER_HANDLER_H \ No newline at end of file diff --git a/utils/http_over_curl/include/manual_reset_event.h b/utils/http_over_curl/include/manual_reset_event.h index 9c60dbfc5..a592b1029 100644 --- a/utils/http_over_curl/include/manual_reset_event.h +++ b/utils/http_over_curl/include/manual_reset_event.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -31,6 +31,15 @@ struct ManualResetEvent { underlying_ = eventfd(0, 0); } + explicit ManualResetEvent(bool isSemaphore) + { + if (isSemapuhore) { + underlying_ = eventfd(0, EFD_SEMAPHORE); + } else { + underlying_ = eventfd(0, 0); + } + } + ~ManualResetEvent() { close(underlying_); diff --git a/utils/http_over_curl/include/request_info.h b/utils/http_over_curl/include/request_info.h index 8025146cc..a7204f6e2 100644 --- a/utils/http_over_curl/include/request_info.h +++ b/utils/http_over_curl/include/request_info.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -26,6 +26,9 @@ struct RequestInfo { CURL *easyHandle; TransferStartedCallback startedCallback; TransferDoneCallback doneCallback; +#ifdef HTTP_HANDOVER_FEATURE + TransferHandOverCallback handOverCallback; +#endif void *opaqueData; }; diff --git a/utils/http_over_curl/include/transfer_callbacks.h b/utils/http_over_curl/include/transfer_callbacks.h index f484b1c62..3405407cf 100644 --- a/utils/http_over_curl/include/transfer_callbacks.h +++ b/utils/http_over_curl/include/transfer_callbacks.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -24,6 +24,10 @@ namespace OHOS::NetStack::HttpOverCurl { using TransferDoneCallback = std::function; using TransferStartedCallback = std::function; +#ifdef HTTP_HANDOVER_FEATURE +using TransferHandOverCallback = + std::function; +#endif } // namespace OHOS::NetStack::HttpOverCurl diff --git a/utils/http_over_curl/src/epoll_multi_driver.cpp b/utils/http_over_curl/src/epoll_multi_driver.cpp index 322e70f29..727b343d9 100644 --- a/utils/http_over_curl/src/epoll_multi_driver.cpp +++ b/utils/http_over_curl/src/epoll_multi_driver.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -20,6 +20,10 @@ #if HAS_NETSTACK_CHR #include "netstack_chr_client.h" #endif +#ifdef HTTP_HANDOVER_FEATURE +#include "http_handover_handler.h" +#include "request_context.h" +#endif namespace OHOS::NetStack::HttpOverCurl { @@ -31,8 +35,22 @@ EpollMultiDriver::EpollMultiDriver(const std::shared_ptr> &incomingQueue, + std::shared_ptr &netHandoverHandler) + : incomingQueue_(incomingQueue), netHandoverHandler_(netHandoverHandler) +{ + Initialize(); +} +#endif + void EpollMultiDriver::Initialize() { +#ifdef HTTP_HANDOVER_FEATURE + if (netHandoverHandler_) { + netHandoverHandler_->RegisterForPolling(poller_); + } +#endif timeoutTimer_.RegisterForPolling(poller_); incomingQueue_->GetSyncEvent().RegisterForPolling(poller_); multi_ = curl_multi_init(); @@ -88,6 +106,10 @@ void EpollMultiDriver::Step(int waitEventsTimeoutMs) IncomingRequestCallback(); } else if (timeoutTimer_.IsItYours(events[idx].data.fd)) { EpollTimerCallback(); +#ifdef HTTP_HANDOVER_FEATURE + } else if (netHandoverHandler_ && netHandoverHandler_->IsItYours(events[idx].data.fd)) { + HandOverRequestCallback(); +#endif } else { // curl socket event EpollSocketCallback(events[idx].data.fd); } @@ -98,6 +120,12 @@ void EpollMultiDriver::IncomingRequestCallback() { auto requestsToAdd = incomingQueue_->Flush(); for (auto &request : requestsToAdd) { +#ifdef HTTP_HANDOVER_FEATURE + if (netHandoverHandler_ && netHandoverHandler_->NeedFlowControl(request)) { + NETSTACK_LOGI("incoming request"); + continue; + } +#endif ongoingRequests_[request->easyHandle] = request; auto ret = curl_multi_add_handle(multi_, request->easyHandle); if (ret != CURLM_OK) { @@ -155,6 +183,14 @@ __attribute__((no_sanitize("cfi"))) void EpollMultiDriver::CheckMultiInfo() curl_multi_remove_handle(multi_, easyHandle); auto requestInfo = ongoingRequests_[easyHandle]; ongoingRequests_.erase(easyHandle); +#ifdef HTTP_HANDOVER_FEATURE + if (netHandoverHandler_) { + if (netHandoverHandler_->ProcessRequestErr(easyHandle, ongoingRequests_, multi_, requestInfo, + message)) { + break; + } + } +#endif if (requestInfo != nullptr && requestInfo->doneCallback) { requestInfo->doneCallback(message, requestInfo->opaqueData); } diff --git a/utils/http_over_curl/src/epoll_request_handler.cpp b/utils/http_over_curl/src/epoll_request_handler.cpp index 71108813c..4242a1245 100644 --- a/utils/http_over_curl/src/epoll_request_handler.cpp +++ b/utils/http_over_curl/src/epoll_request_handler.cpp @@ -20,6 +20,9 @@ #include "epoll_multi_driver.h" #include "netstack_log.h" #include "request_info.h" +#ifdef HTTP_HANDOVER_FEATURE +#include "http_handover_handler.h" +#endif namespace OHOS::NetStack::HttpOverCurl { static constexpr const char *HTTP_WORK_THREAD = "OS_NET_HttpWork"; @@ -30,6 +33,14 @@ EpollRequestHandler::EpollRequestHandler(int sleepTimeoutMs) { } +#ifdef HTTP_HANDOVER_FEATURE +EpollRequestHandler::EpollRequestHandler(int sleepTimeoutMs, bool netHandover) + : sleepTimeoutMs_(sleepTimeoutMs), netHandover_(netHandover), + incomingQueue_(std::make_shared>()) +{ +} +#endif + EpollRequestHandler::~EpollRequestHandler() { stop_ = true; @@ -38,6 +49,29 @@ EpollRequestHandler::~EpollRequestHandler() } } +#ifdef HTTP_HANDOVER_FEATURE +void EpollRequestHandler::Process(CURL *easyHandle, const TransferStartedCallback &startedCallback, + const TransferDoneCallback &responseCallback, const TransferHandOverCallback &handOverCallback, void *opaqueData) +{ + auto requestInfo = new RequestInfo{easyHandle, startedCallback, responseCallback, handOverCallback, opaqueData}; + incomingQueue_->Push(requestInfo); + + auto start = [this]() { + auto f = [this]() { +#if defined(MAC_PLATFORM) || defined(IOS_PLATFORM) + pthread_setname_np(HTTP_WORK_THREAD); +#else + pthread_setname_np(pthread_self(), HTTP_WORK_THREAD); +#endif + WorkingThread(); + }; + workThread_ = std::thread(f); + workThread_.detach(); + }; + + std::call_once(init_, start); +} +#else void EpollRequestHandler::Process(CURL *easyHandle, const TransferStartedCallback &startedCallback, const TransferDoneCallback &responseCallback, void *opaqueData) { @@ -59,10 +93,29 @@ void EpollRequestHandler::Process(CURL *easyHandle, const TransferStartedCallbac std::call_once(init_, start); } +#endif + +#ifdef HTTP_HANDOVER_FEATURE +bool EpollRequestHandler::GetRequestHandOver() +{ + return netHandover_; +} +#endif void EpollRequestHandler::WorkingThread() { +#ifdef HTTP_HANDOVER_FEATURE + std::shared_ptr netHandoverHandler = std::make_shared(); + if (netHandover_ && netHandoverHandler->InitSuccess()) { + NETSTACK_LOGI("NetHandover enabled"); + } else { + netHandoverHandler = nullptr; + NETSTACK_LOGI("NetHandover disabled!!!"); + } + EpollMultiDriver requestHandler(incomingQueue_, netHandoverHandler); +#else EpollMultiDriver requestHandler(incomingQueue_); +#endif while (!stop_) { requestHandler.Step(sleepTimeoutMs_); diff --git a/utils/http_over_curl/src/http_handover_handler.cpp b/utils/http_over_curl/src/http_handover_handler.cpp new file mode 100644 index 000000000..c53c5d83e --- /dev/null +++ b/utils/http_over_curl/src/http_handover_handler.cpp @@ -0,0 +1,423 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "http_handover_handler.h" +#include +#include "netstack_log.h" +#include "request_info.h" +#include "request_context.h" + +namespace OHOS::NetStack::HttpOverCurl { + +const char *const METHOD_GET = "GET"; +const char *const METHOD_HEAD = "HEAD"; +const char *const METHOD_OPTIONS = "OPTIONS"; +const char *const METHOD_TRACE = "TRACE"; + +HttpHandoverHandler::HttpHandoverHandler() + : handOverEvent_(std::make_unique(true)) +{ + NETSTACK_LOGI("HttpHandoverHandler init"); + initsuccess_ = Initialize(); +} + +void handOverCallback(void *user) +{ + NETSTACK_LOGI("handOverCallback enter"); + if (user == nullptr) { + NETSTACK_LOGE("user is nullptr"); + return; + } + + HttpHandoverHandler* const handoverhandler = reinterpret_cast(user); + handoverhandler->Set(); +} + +bool HttpHandoverHandler::InitSuccess() +{ + return initsuccess_; +} + +bool HttpHandoverHandler::Initialize() +{ + const std::string HTTP_HANDOVER_WRAPPER_PATH = "/system/lib64/libhttp_handover.z.so"; + if (netHandoverHandler_ == nullptr) { + netHandoverHandler_ = dlopen(HTTP_HANDOVER_WRAPPER_PATH.c_str(), RTLD_NOW); + if (netHandoverHandler_ == nullptr) { + NETSTACK_LOGE("libhttp_handover.z.so was not loaded, error: %{public}s", dlerror()); + return false; + } + } + httpHandOverInit_ = (HTTP_HAND_OVER_INIT)dlsym(netHandoverHandler_, "HMS_NetworkBoost_HttpHandoverManagerInit"); + httpHandOverUninit_ = + (HTTP_HAND_OVER_UNINIT)dlsym(netHandoverHandler_, "HMS_NetworkBoost_HttpHandoverManagerUninit"); + httpHandOverQuery_ = + (HTTP_HAND_OVER_QUERY)dlsym(netHandoverHandler_, "HMS_NetworkBoost_HttpHandoverManagerQuery"); + httpHandOverAddRequest_ = + (HTTP_HAND_OVER_ADD)dlsym(netHandoverHandler_, "HMS_NetworkBoost_HttpHandoverManagerAddRequest"); + httpHandOverDelRequest_ = + (HTTP_HAND_OVER_DEL)dlsym(netHandoverHandler_, "HMS_NetworkBoost_HttpHandoverManagerDelRequest"); + httpHandOverQueryRequest_ = + (HTTP_HAND_OVER_QUERY_REQUEST)dlsym(netHandoverHandler_, "HMS_NetworkBoost_HttpHandoverManagerQueryRequest"); + bool hasFuncNull = (httpHandOverInit_ == nullptr || httpHandOverUninit_ == nullptr || + httpHandOverQuery_ == nullptr || httpHandOverAddRequest_ == nullptr || httpHandOverDelRequest_ == nullptr || + httpHandOverQueryRequest_ == nullptr); + if (hasFuncNull) { + NETSTACK_LOGE("[HTTP HANDOVER] http handover wrapper symbol failed, error: %{public}s", dlerror()); + return false; + } + NETSTACK_LOGI("NetHandover enabled"); + + if (netHandoverHandler_ != nullptr) { + httpHandOverManager_ = httpHandOverInit_(this, handOverCallback); + } + return true; +} + +HttpHandoverHandler::~HttpHandoverHandler() +{ + if (httpHandOverManager_ != nullptr) { + NETSTACK_LOGD("start httpHandOverUninit_"); + httpHandOverUninit_(httpHandOverManager_); + } + + if (netHandoverHandler_ != nullptr) { + dlclose(netHandoverHandler_); + netHandoverHandler_ = nullptr; + } + httpHandOverInit_ = nullptr; + httpHandOverUninit_ = nullptr; +} + +void HttpHandoverHandler::RegisterForPolling(Epoller &poller) const +{ + handOverEvent_->RegisterForPolling(poller); +} + +bool HttpHandoverHandler::IsItYours(FileDescriptor descriptor) const +{ + return handOverEvent_->IsItYours(descriptor); +} + +void HttpHandoverHandler::Set() +{ + handOverEvent_->Set(); +} + +void HttpHandoverHandler::HandOverQuery(int32_t &status, int32_t &netId) +{ + if (httpHandOverQuery_ == nullptr) { + NETSTACK_LOGD("nullptr param error"); + return; + } + return httpHandOverQuery_(httpHandOverManager_, status, netId); +} + +bool HttpHandoverHandler::CheckSocketOpentimeLessThanEndTime(curl_socket_t fd) +{ + if (socketopentime_.count(fd) == 0) { + return false; + } + bool ret = socketopentime_[fd] < endTime_; + if (ret) { + NETSTACK_LOGI("Old fd:%{public}d fdtime:%{public}d endTime:%{public}d", (int)fd, socketopentime_[fd], endTime_); + } + return ret; +} + +void SetSocketOpenTime(curl_socket_t fd) +{ + socketopentime_[fd] = endTime; +} + +void EraseFd(curl_socket_t fd) +{ + if (socketopentime_.count(fd) == 0) { + return ; + } + socketopentime_.erase(fd); +} + +void SetCallback(RequestInfo *request) +{ + static auto checksockettime = +[](void *user, curl_socket_t fd) -> bool { + auto handover = static_cast(user); + if (handover && handover->CheckSocketOpentimeLessThanEndTime(fd)) { + return false; + } + return True; + }; + + curl_easy_setopt(request->easyHandle, CURLOPT_CONNREUSEDATA, this); + curl_easy_setopt(request->easyHandle, CURLOPT_CONNREUSEFUNCTION, checksockettime); + + static auto opensocket = +[](void *user, curlsocktype purpose, struct cuel_sockaddr *addr) -> curl_socket_t { + curl_socket_t sockfd = socket(addr_family, addr->socktype, addr->protocol); + if (sockfd < 0) { + NETSTACK_LOGI("Failled to open socket: %{public}d, error: %{public}d", sockfd, errno); + return -1; + } + auto handover = static_cast(user); + if (handover) { + handover->SetSocketOpenTime(sockfd); + } + return sockfd; + }; + + curl_easy_setopt(request->easyHandle, CURLOPT_CONNREUSEDATA, this); + curl_easy_setopt(request->easyHandle, CURLOPT_CONNREUSEFUNCTION, opensocket); + + static auto closeSocketCallback = +[](void *user, curl_socket_t fd) -> int { + auto handover = static_cast(user); + if (handover) { + handover->EraseFd(fd); + } + if (close(fd) < 0) { + NETSTACK_LOGI("Failed to close socket: %{publlic}d, errno: %{public}d", fd, errno); + return -1; + } + return 0; + }; + + curl_easy_setopt(request->easyHandle, CURLOPT_CONNREUSEDATA, this); + curl_easy_setopt(request->easyHandle, CURLOPT_CONNREUSEFUNCTION, closeSocketCallback); +} + +bool HttpHandoverHandler::TryFlowControl(RequestInfo *requestInfo) +{ + int32_t status = -1; + int32_t netId = -1; + HandOverQuery(status, netId); + SetCallback(requestInfo); + if (status == HttpHandoverHandler::START) { + handoverQueue_.insert(requestInfo); + auto context = static_cast(requestInfo->opaqueData); + NETSTACK_LOGI("taskid=%{public}d, FlowControl", context->GetTaskId()); + AddRequest(requestInfo->opaqueData, true, IsRequestRead(requestInfo->easyHandle)); + return true; + } + AddRequest(requestInfo->opaqueData, false, IsRequestRead(requestInfo->easyHandle)); + return false; +} + +void HttpHandoverHandler::SetEndTime() +{ + ++endTime_; + NETSTACK_LOGI("endTime: %{public}d, flowcontrol queue size %{public}d", endTime_, (int)handoverQueue_.size()); +} + +bool HttpHandoverHandler::RetransRequest(std::map &ongoingRequests, CURLM *multi, + RequestInfo *request); +{ + auto ret = curl_multi_add_handle(multi, request->easyHandle); + if (ret != CURLM_OK) { + NETSTACK_LOGI("curl_multi_add_handle err, ret = %{public}d %{public}s", ret, curl_multi_strerror(ret)); + return false; + } + ongoingRequests[request->easyHandle] = request; + return true; +} + +bool HttpHandoverHandler::CheckRequestCanRetrans(RequestInfo *request) +{ + time_t recvtime = 0; + time_t sendtime = 0; + int32_t isRead = IsRequestRead(request->easyHandle, recvtime, sendtime); + if (isRead == -1) { + return false; + } + auto context = static_cast(request->opaqueData); + auto method = context->options.GetMethod(); + int isInstream = context->IsRequestInStream(); + uint32_t readTiemout = context->options.GetReadTimeout(); + uint32_t connecttimeout = context->options.GetConnectTimeout(); + NETSTACK_LOGI( + "taskid=%{public}d," + "method:%{public}s Instream:%{public}d, recvtime:%{public}d, sendtime:%{public}d, readTimeout:%{public}u" + "connecttimeout:%{public}u, url:%{public}s ", context->GetTaskId(), method.c_str(), + isInstream, (int)recvtime, (int)sendtime, readTimeout, connecttimeout, context->options.GetUrl().c_str()); + + if (sendtime == 0) { + return true; + } + bool isSafe = (method == METHOD_GET || method == METHOD_HEAD || method == METHOD_OPTIONS || method == METHOD_TRACE); + if(!isSafe) { + return false; + } + if (isRead == 0 || !context->IsRequestInStream()) { + return true; + } + return false; +} + +void HttpHandoverHandler::RetransFailedHandle(std::map &ongoingRequests, + std::queue &retransfailed) +{ + while (!retransfailed.empty()) { + auto &handle = retransfailed.front(); + retrransfailed.pop(); + if (!ongoingRequest.count(handle)) { + continue; + } + auto request = ongoingRequests[handle]; + if (request != nullptr && request->doneCallback) { + CURLMsg message; + message.msg = CURLMSG_DONE; + message.data.result = CURL_SEND_ERROR; + request->doneCallback(&message, request->opaqueData); + } + ongoingRequests.erase(handle); + } +} + +void HttpHandoverHandler::HandOverRequestCallback(std::map &ongoingRequests, CURLM *multi) +{ + handOverEvent_ ->Reset(); + int32_t status = -1; + int32_t netId = -1; + HandOverQuery(status, netId); + NETSTACK_LOGI("Enter HandoverRequestCallback status %{public}d", status); + if (status == HttpHandoverHandler::START) { + NETSTACK_LOGI("ongoingRequests:%{public}d", (int)ongoingRequest.size()); + for (auto %request : ongoingRequests) { + if (requestEndtime_.count(request.second) == 0) { + requestEndtime_[request.second] = endTime; + } + (void)CheckRequestCanRetrans(request.second); + } + } else if (status == HttpHandoverHandler::END || status == HttpHandoverHandler::FATAL) { + if (status == HttpHandoverHandler::END) { + NETSTACK_LOGI("ongoingRequests:%{public}d, retrans:%{public}d", (int)ongoingRequests.size(), retrans_); + SetEndTime(); + srd::queue retransfailed; + for (auto &request : ongoingRequests) { + if (CheckRequestCanRetrans(request.second)) { + curl_multi_remove_handle(multi, request.first); + if (RetransRequest(ongoingRequest, multi, request.second)) { + ++retrans_; + } else { + retransfailed.push(request.first); + } + } + } + RetransFailedHandle(ongoingRequests, retransfailed); + } + NETSTACK_LOGI("handoverQueue_:%{public}d, retrans:%{public}d", (int)handoverQueue_.size(), retrans_); + for (auto &request : handoverQueue_) { + (void) RetransRequest(ongoingRequests, multi, request); + } + handoverQueue_.clead(); + retrans_ = 0; + } +} + +int32_t HttpHandoverHandler::IsRequestRead(CURL *easyHandle) +{ + time_t recvtime = 0; + time_t sendtime = 0; + return IsRequestRead(easyHandle, recvtime, sendtime); +} + +int32_t HttpHandoverHandler::IsRequestRead(CURL *easyHandle, time_t &recvtime, time_t &sendtime) +{ + CURLcode result = curl_easy_getinfo(easyHandle, CURLINFO_STARTTRANSFER_TIME_T, &recvtime); + if (result != CURL_OK) { + NETSTACK_LOGI("get recv time failed:%{public}s", curl_easy_strerror(result)); + return -1; + } + result = curl_easy_getinfo(easyHandle, CURLINFO_PRETRANSFER_TIME_T, &sendtime); + if (result != CURL_OK) { + NETSTACK_LOGI("get send time failed:%{public}s", curl_easy_strerror(result)); + return -1; + } + return (recvtime == 0 || sendtime == recvtime) ? 0 : 1; +} + +bool HttpHandoverHandler::ProcessRequestErr(CURL *easyHandle, std::map &ongoingRequests, + CURLM *multi, RequestInfo *requestInfo, CURLMsg *msg) +{ + if (CheckRequestNetError(ongoingRequests, multi, requestInfo, msg)) { + return true; + } + SetHandOverInfo(easyHandle, RequestInfo); + return false; +} + +void HttpHandoverHandler::SetHandOverInfo(CURL *easyHandle, RequestInfo *requestInfo) +{ + if (requestInfo != nullptr) { + int32_t handOverReason = 0; + double flowControlTime = 0; + int32_t isRead = 0; + int32_t handOverNum = QueryRequest(requestInfo->opaqueData, handOverReason, flowControlTime, isRead); + if (requestInfo->handOverCallback) { + requestInfo->handOverCallback(requestInfo->opaqueData, handOverNum, handOverReason, flowControlTime, + isRead); + } + DelRequest(requestInfo->opaqueData); + } + return; +} + +bool HttpHandoverHandler::CheckRequestNetError(std::map &ongoingRequests, CURLM multi, + RequestInfo *requestInfo, CURLMsg *msg) +{ + if (!RequestInfo || requestEndtime_.count(RequestInfo) == 0) { + return false; + } + int endTime = requestEndtime_[requestInfo]; + requestEndtime_.erase(requestInfo); + if (!msg || (msg->data.result != CURL_SEND_ERROR && msg->data.result != CURLE_RECV_ERROR)) { + return false; + } + if (!CheckRequestCanRetrans(requestInfo)) { + return false; + } + if (TryFlowControl(requestInfo)) { + ++retrans; + return true; + } + if (endTime == endTime_ - 1) { + NETSTACK_LOGI("networkerror afteer end status"); + AddRequest(requestInfo->opaqueData, true, IsRequestRead(requestInfo->easyHandle)); + return RetransRequest(ongoingRequests, multi, requestInfo); + } + return false; +} + +void HttpHandoverHandler::AddRequest(void *userp, bool isHandOver, int32_t isRead) +{ + if (isHandOver) { + NETSTACK_LOGI("HttpHandoverHandler AddRequest"); + } + httoHandOverAddRequest_(httpHandOverManager_, userp, isHandOver, isRead); +} + +void HttpHandoverHandler::DelRequest(void *userp) +{ + auto context = static_cast(userp); + if (context->IsParseOK() && context->IsExecOK()) { + httpHandOverDelRequest_(httpHandOverManager_, userp, true); + return; + } + httphandOverQueryRequest_(httpHandOverManager_, userp, false); +} + +int32_t HttpHandoverHandler::QueryRequest(void *userp, int32_t &handOverReason, double &flowControlTime, + int32_t &isRead) +{ + return httphandOverQueryRequest_(httpHandOverManager_, userp, &handOverReason, double &flowControlTime, &isRead); +} +} \ No newline at end of file -- Gitee From 3fad8f39aad046208f124afe0ee0c5b0e3d61b63 Mon Sep 17 00:00:00 2001 From: YangWeimin Date: Thu, 29 May 2025 08:44:25 +0800 Subject: [PATCH 2/6] fix build.gn and codecheck problem Signed-off-by: YangWeimin --- frameworks/js/napi/http/BUILD.gn | 2 +- frameworks/js/napi/http/http_exec/src/http_exec.cpp | 3 ++- utils/http_over_curl/src/epoll_request_handler.cpp | 2 +- utils/http_over_curl/src/http_handover_handler.cpp | 10 +++++----- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/frameworks/js/napi/http/BUILD.gn b/frameworks/js/napi/http/BUILD.gn index f2d6da3d1..fac56a4ae 100644 --- a/frameworks/js/napi/http/BUILD.gn +++ b/frameworks/js/napi/http/BUILD.gn @@ -173,7 +173,7 @@ ohos_shared_library("http") { "$NETSTACK_DIR/utils/http_over_curl/src/epoll_request_handler.cpp", "$NETSTACK_DIR/utils/http_over_curl/src/http_handover_handler.cpp", ] - defines = [ "HTTP_HANDOVER_FEATURE" ] + defines += [ "HTTP_HANDOVER_FEATURE" ] } else { defines = [ "HAS_NETMANAGER_BASE=0", diff --git a/frameworks/js/napi/http/http_exec/src/http_exec.cpp b/frameworks/js/napi/http/http_exec/src/http_exec.cpp index a1e64ba21..addd2fa3e 100755 --- a/frameworks/js/napi/http/http_exec/src/http_exec.cpp +++ b/frameworks/js/napi/http/http_exec/src/http_exec.cpp @@ -120,6 +120,7 @@ static constexpr const char *HTTP_AF_ONLYV4 = "ONLY_V4"; static constexpr const char *HTTP_AF_ONLYV6 = "ONLY_V6"; #ifdef HTTP_HANDOVER_FEATURE static bool IsHandOverFeature = false; +static constexpr const int32_t SLEEP_TIMEOUT_MS = 5000; #endif static void RequestContextDeleter(RequestContext *context) @@ -288,7 +289,7 @@ bool HttpExec::AddCurlHandle(CURL *handle, RequestContext *context) StartAsyncTrace(HITRACE_TAG_NET, context->GetTraceName(), context->GetTaskId()); SetServerSSLCertOption(handle, context); - static HttpOverCurl::EpollRequestHandler requestHandler(5000, true); + static HttpOverCurl::EpollRequestHandler requestHandler(SLEEP_TIMEOUT_MS, true); static auto startedCallback = +[](CURL *easyHandle, void *opaqueData) { char *url = nullptr; diff --git a/utils/http_over_curl/src/epoll_request_handler.cpp b/utils/http_over_curl/src/epoll_request_handler.cpp index 4242a1245..03f41b498 100644 --- a/utils/http_over_curl/src/epoll_request_handler.cpp +++ b/utils/http_over_curl/src/epoll_request_handler.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/utils/http_over_curl/src/http_handover_handler.cpp b/utils/http_over_curl/src/http_handover_handler.cpp index c53c5d83e..59c1957ea 100644 --- a/utils/http_over_curl/src/http_handover_handler.cpp +++ b/utils/http_over_curl/src/http_handover_handler.cpp @@ -218,7 +218,7 @@ void HttpHandoverHandler::SetEndTime() NETSTACK_LOGI("endTime: %{public}d, flowcontrol queue size %{public}d", endTime_, (int)handoverQueue_.size()); } -bool HttpHandoverHandler::RetransRequest(std::map &ongoingRequests, CURLM *multi, +bool HttpHandoverHandler::RetransRequest(std::map &ongoingRequests, CURLM *multi, RequestInfo *request); { auto ret = curl_multi_add_handle(multi, request->easyHandle); @@ -253,7 +253,7 @@ bool HttpHandoverHandler::CheckRequestCanRetrans(RequestInfo *request) return true; } bool isSafe = (method == METHOD_GET || method == METHOD_HEAD || method == METHOD_OPTIONS || method == METHOD_TRACE); - if(!isSafe) { + if (!isSafe) { return false; } if (isRead == 0 || !context->IsRequestInStream()) { @@ -262,7 +262,7 @@ bool HttpHandoverHandler::CheckRequestCanRetrans(RequestInfo *request) return false; } -void HttpHandoverHandler::RetransFailedHandle(std::map &ongoingRequests, +void HttpHandoverHandler::RetransFailedHandle(std::map &ongoingRequests, std::queue &retransfailed) { while (!retransfailed.empty()) { @@ -345,7 +345,7 @@ int32_t HttpHandoverHandler::IsRequestRead(CURL *easyHandle, time_t &recvtime, t return (recvtime == 0 || sendtime == recvtime) ? 0 : 1; } -bool HttpHandoverHandler::ProcessRequestErr(CURL *easyHandle, std::map &ongoingRequests, +bool HttpHandoverHandler::ProcessRequestErr(CURL *easyHandle, std::map &ongoingRequests, CURLM *multi, RequestInfo *requestInfo, CURLMsg *msg) { if (CheckRequestNetError(ongoingRequests, multi, requestInfo, msg)) { @@ -415,7 +415,7 @@ void HttpHandoverHandler::DelRequest(void *userp) httphandOverQueryRequest_(httpHandOverManager_, userp, false); } -int32_t HttpHandoverHandler::QueryRequest(void *userp, int32_t &handOverReason, double &flowControlTime, +int32_t HttpHandoverHandler::QueryRequest(void *userp, int32_t &handOverReason, double &flowControlTime, int32_t &isRead) { return httphandOverQueryRequest_(httpHandOverManager_, userp, &handOverReason, double &flowControlTime, &isRead); -- Gitee From 513b927eb75405b77e77f31d6a9db3f1367121c4 Mon Sep 17 00:00:00 2001 From: YangWeimin Date: Thu, 29 May 2025 10:06:15 +0800 Subject: [PATCH 3/6] modify request_context Signed-off-by: YangWeimin --- .../async_context/include/request_context.h | 28 ++++++++++++++++ .../async_context/src/request_context.cpp | 33 +++++++++++++++++++ .../include/http_handover_handler.h | 4 +-- .../include/manual_reset_event.h | 2 +- .../http_over_curl/src/epoll_multi_driver.cpp | 2 +- .../src/http_handover_handler.cpp | 10 +++--- 6 files changed, 70 insertions(+), 9 deletions(-) diff --git a/frameworks/js/napi/http/async_context/include/request_context.h b/frameworks/js/napi/http/async_context/include/request_context.h index dc7a92c9e..27d5dc5c9 100644 --- a/frameworks/js/napi/http/async_context/include/request_context.h +++ b/frameworks/js/napi/http/async_context/include/request_context.h @@ -50,6 +50,17 @@ struct CertsPath { std::string certFile; }; +#ifdef HTTP_HANDOVER_FEATURE +struct RequestHandOverInfo { + RequestHandOverInfo() = default; + ~RequestHandOverInfo() = default; + int32_t handOverNum; + int32_t handOverReason; + double flowControlTime; + bool isRead; +}; +#endif + class RequestContext final : public BaseContext { public: friend class HttpExec; @@ -140,6 +151,12 @@ public: [[nodiscard]] std::string GetBundleName() const; +#ifdef HTTP_HANDOVER_FEATURE + void SetTraceName(const std::string &traceName); + + [[nodiscard]] std::string GetTraceName() const; +#endif + void SetCurlHandle(CURL *handle); void SendNetworkProfiler(); @@ -157,6 +174,11 @@ public: void SetPinnedPubkey(std::string &pubkey); std::string GetPinnedPubkey() const; +#ifdef HTTP_HANDOVER_FEATURE + void SetRequestHandOverInfo(int32_t handOverNum, int32_t handOverReason, double flowControlTime, bool isRead); + + const RequestHandOverInfo &GetRequestHandOverInfo(); +#endif private: uint32_t magicNumber_ = MAGIC_NUMBER; int32_t taskId_ = -1; @@ -178,6 +200,9 @@ private: curl_slist *curlHostList_ = nullptr; bool isAtomicService_ = false; std::string bundleName_; +#ifdef HTTP_HANDOVER_FEATURE + std::string traceName_; +#endif bool isRootCaVerified_ = false; bool isRootCaVerifiedOk_ = false; std::string pinnedPubkey_; @@ -185,6 +210,9 @@ private: std::unique_ptr networkProfilerUtils_; #endif CURL *curlHandle_; +#ifdef HTTP_HANDOVER_FEATURE + RequestHandOverInfo requestHandOverInfo_; +#endif RequestTracer::Trace trace_; bool CheckParamsType(napi_value *params, size_t paramsCount); diff --git a/frameworks/js/napi/http/async_context/src/request_context.cpp b/frameworks/js/napi/http/async_context/src/request_context.cpp index 38b5224bf..10ef730b2 100755 --- a/frameworks/js/napi/http/async_context/src/request_context.cpp +++ b/frameworks/js/napi/http/async_context/src/request_context.cpp @@ -92,6 +92,11 @@ RequestContext::RequestContext(napi_env env, const std::shared_ptr bundleName_(""), trace_("HttpRequest_" + std::to_string(taskId_)) { +#ifdef HTTP_HANDOVER_FEATURE + taskId_ = g_currentTaskId++; + isAtomicService_ = false; + bundleName_ = ""; +#endif StartTiming(); #if HAS_NETMANAGER_BASE networkProfilerUtils_ = std::make_unique(); @@ -982,6 +987,18 @@ std::string RequestContext::GetBundleName() const return bundleName_; } +#ifdef HTTP_HANDOVER_FEATURE +void RequestContext::SetTraceName(const std::string &traceName) +{ + traceName_ = traceName; +} + +std::string RequestContext::GetTraceName() const +{ + return traceName_; +} +#endif + void RequestContext::SetCurlHandle(CURL *handle) { curlHandle_ = handle; @@ -1030,6 +1047,22 @@ std::string RequestContext::GetPinnedPubkey() const return pinnedPubkey_; } +#ifdef HTTP_HANDOVER_FEATURE +void RequestContext::SetRequestHandOverInfo(inte32_t handOverNum, int32_t handOverReason, double flowControlTime, + bool isRead) +{ + requestHandOverInfo_.handOverNum = handOverNum; + requestHandOverInfo_.handOverReason = handOverReason; + requestHandOverInfo_.flowControlTime = flowControlTime; + requestHandOverInfo_.isRead = isRead; +} + +const ReequestHandOverInfo &RequestContext::GetRequestHandOverInfo() +{ + return requestHandOverInfo_; +} +#endif + void RequestContext::ParseAddressFamily(napi_value optionsValue) { std::string addressFamily = NapiUtils::GetStringPropertyUtf8(GetEnv(), optionsValue, diff --git a/utils/http_over_curl/include/http_handover_handler.h b/utils/http_over_curl/include/http_handover_handler.h index f3dcb7735..69a5fbd51 100644 --- a/utils/http_over_curl/include/http_handover_handler.h +++ b/utils/http_over_curl/include/http_handover_handler.h @@ -61,7 +61,7 @@ public: bool ProcessRequestErr(CURL *easyHandle, std::map &ongoingRequests, CURLM *multi, RequestInfo *requestInfo, CURLMsg *msg); void SetHandOverInfo(CURL *easyHandle, RequestInfo *requestInfo); - bool CheckRequestNetError(std::map &ongoingRequests, CURLM multi, + bool CheckRequestNetError(std::map &ongoingRequests, CURLM *multi, RequestInfo *requestInfo, CURLMsg *msg); void AddRequest(void *userp, bool isHandOver, int32_t isRead); void DelRequest(void *userp); @@ -85,7 +85,7 @@ private: HTTP_HAND_OVER_QUERY httpHandOverQuery_ = nullptr; HTTP_HAND_OVER_ADD httpHandOverAddRequest_ = nullptr; HTTP_HAND_OVER_DEL httpHandOverDelRequest_ = nullptr; - HTTP_HAND_OVER_QUERY_REQUEST httphandOverQueryRequest_ = nullptr; + HTTP_HAND_OVER_QUERY_REQUEST httpHandOverQueryRequest_ = nullptr; std::set handoverQueue_; std::map socketopentime_; std::map requestEndtime_; diff --git a/utils/http_over_curl/include/manual_reset_event.h b/utils/http_over_curl/include/manual_reset_event.h index a592b1029..1199e0cb2 100644 --- a/utils/http_over_curl/include/manual_reset_event.h +++ b/utils/http_over_curl/include/manual_reset_event.h @@ -33,7 +33,7 @@ struct ManualResetEvent { explicit ManualResetEvent(bool isSemaphore) { - if (isSemapuhore) { + if (isSemaphore) { underlying_ = eventfd(0, EFD_SEMAPHORE); } else { underlying_ = eventfd(0, 0); diff --git a/utils/http_over_curl/src/epoll_multi_driver.cpp b/utils/http_over_curl/src/epoll_multi_driver.cpp index 727b343d9..b7d392e59 100644 --- a/utils/http_over_curl/src/epoll_multi_driver.cpp +++ b/utils/http_over_curl/src/epoll_multi_driver.cpp @@ -121,7 +121,7 @@ void EpollMultiDriver::IncomingRequestCallback() auto requestsToAdd = incomingQueue_->Flush(); for (auto &request : requestsToAdd) { #ifdef HTTP_HANDOVER_FEATURE - if (netHandoverHandler_ && netHandoverHandler_->NeedFlowControl(request)) { + if (netHandoverHandler_ && netHandoverHandler_->TryFlowControl(request)) { NETSTACK_LOGI("incoming request"); continue; } diff --git a/utils/http_over_curl/src/http_handover_handler.cpp b/utils/http_over_curl/src/http_handover_handler.cpp index 59c1957ea..15ccbc724 100644 --- a/utils/http_over_curl/src/http_handover_handler.cpp +++ b/utils/http_over_curl/src/http_handover_handler.cpp @@ -139,7 +139,7 @@ bool HttpHandoverHandler::CheckSocketOpentimeLessThanEndTime(curl_socket_t fd) void SetSocketOpenTime(curl_socket_t fd) { - socketopentime_[fd] = endTime; + socketopentime_[fd] = endTime_; } void EraseFd(curl_socket_t fd) @@ -157,14 +157,14 @@ void SetCallback(RequestInfo *request) if (handover && handover->CheckSocketOpentimeLessThanEndTime(fd)) { return false; } - return True; + return true; }; curl_easy_setopt(request->easyHandle, CURLOPT_CONNREUSEDATA, this); curl_easy_setopt(request->easyHandle, CURLOPT_CONNREUSEFUNCTION, checksockettime); - static auto opensocket = +[](void *user, curlsocktype purpose, struct cuel_sockaddr *addr) -> curl_socket_t { - curl_socket_t sockfd = socket(addr_family, addr->socktype, addr->protocol); + static auto opensocket = +[](void *user, curlsocktype purpose, struct curl_sockaddr *addr) -> curl_socket_t { + curl_socket_t sockfd = socket(addr->family, addr->socktype, addr->protocol); if (sockfd < 0) { NETSTACK_LOGI("Failled to open socket: %{public}d, error: %{public}d", sockfd, errno); return -1; @@ -180,7 +180,7 @@ void SetCallback(RequestInfo *request) curl_easy_setopt(request->easyHandle, CURLOPT_CONNREUSEFUNCTION, opensocket); static auto closeSocketCallback = +[](void *user, curl_socket_t fd) -> int { - auto handover = static_cast(user); + auto handover = static_cast(user); if (handover) { handover->EraseFd(fd); } -- Gitee From e464d35ed9792e43dee2576fa6785c5bfda78736 Mon Sep 17 00:00:00 2001 From: YangWeimin Date: Thu, 29 May 2025 10:36:06 +0800 Subject: [PATCH 4/6] fix some spelling problem Signed-off-by: YangWeimin --- utils/http_over_curl/include/request_info.h | 2 +- .../src/http_handover_handler.cpp | 24 +++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/utils/http_over_curl/include/request_info.h b/utils/http_over_curl/include/request_info.h index a7204f6e2..14ad196f5 100644 --- a/utils/http_over_curl/include/request_info.h +++ b/utils/http_over_curl/include/request_info.h @@ -27,7 +27,7 @@ struct RequestInfo { TransferStartedCallback startedCallback; TransferDoneCallback doneCallback; #ifdef HTTP_HANDOVER_FEATURE - TransferHandOverCallback handOverCallback; + TransferHandOverCallback HandOverCallback; #endif void *opaqueData; }; diff --git a/utils/http_over_curl/src/http_handover_handler.cpp b/utils/http_over_curl/src/http_handover_handler.cpp index 15ccbc724..31ad9c672 100644 --- a/utils/http_over_curl/src/http_handover_handler.cpp +++ b/utils/http_over_curl/src/http_handover_handler.cpp @@ -33,9 +33,9 @@ HttpHandoverHandler::HttpHandoverHandler() initsuccess_ = Initialize(); } -void handOverCallback(void *user) +void HandOverCallback(void *user) { - NETSTACK_LOGI("handOverCallback enter"); + NETSTACK_LOGI("HandOverCallback enter"); if (user == nullptr) { NETSTACK_LOGE("user is nullptr"); return; @@ -81,7 +81,7 @@ bool HttpHandoverHandler::Initialize() NETSTACK_LOGI("NetHandover enabled"); if (netHandoverHandler_ != nullptr) { - httpHandOverManager_ = httpHandOverInit_(this, handOverCallback); + httpHandOverManager_ = httpHandOverInit_(this, HandOverCallback); } return true; } @@ -137,12 +137,12 @@ bool HttpHandoverHandler::CheckSocketOpentimeLessThanEndTime(curl_socket_t fd) return ret; } -void SetSocketOpenTime(curl_socket_t fd) +void HttpHandoverHandler::SetSocketOpenTime(curl_socket_t fd) { socketopentime_[fd] = endTime_; } -void EraseFd(curl_socket_t fd) +void HttpHandoverHandler::EraseFd(curl_socket_t fd) { if (socketopentime_.count(fd) == 0) { return ; @@ -150,7 +150,7 @@ void EraseFd(curl_socket_t fd) socketopentime_.erase(fd); } -void SetCallback(RequestInfo *request) +void HttpHandoverHandler::SetCallback(RequestInfo *request) { static auto checksockettime = +[](void *user, curl_socket_t fd) -> bool { auto handover = static_cast(user); @@ -241,7 +241,7 @@ bool HttpHandoverHandler::CheckRequestCanRetrans(RequestInfo *request) auto context = static_cast(request->opaqueData); auto method = context->options.GetMethod(); int isInstream = context->IsRequestInStream(); - uint32_t readTiemout = context->options.GetReadTimeout(); + uint32_t readTimeout = context->options.GetReadTimeout(); uint32_t connecttimeout = context->options.GetConnectTimeout(); NETSTACK_LOGI( "taskid=%{public}d," @@ -267,15 +267,15 @@ void HttpHandoverHandler::RetransFailedHandle(std::map &o { while (!retransfailed.empty()) { auto &handle = retransfailed.front(); - retrransfailed.pop(); - if (!ongoingRequest.count(handle)) { + retransfailed.pop(); + if (!ongoingRequests.count(handle)) { continue; } auto request = ongoingRequests[handle]; if (request != nullptr && request->doneCallback) { CURLMsg message; message.msg = CURLMSG_DONE; - message.data.result = CURL_SEND_ERROR; + message.data.result = CURLE_SEND_ERROR; request->doneCallback(&message, request->opaqueData); } ongoingRequests.erase(handle); @@ -362,8 +362,8 @@ void HttpHandoverHandler::SetHandOverInfo(CURL *easyHandle, RequestInfo *request double flowControlTime = 0; int32_t isRead = 0; int32_t handOverNum = QueryRequest(requestInfo->opaqueData, handOverReason, flowControlTime, isRead); - if (requestInfo->handOverCallback) { - requestInfo->handOverCallback(requestInfo->opaqueData, handOverNum, handOverReason, flowControlTime, + if (requestInfo->HandOverCallback) { + requestInfo->HandOverCallback(requestInfo->opaqueData, handOverNum, handOverReason, flowControlTime, isRead); } DelRequest(requestInfo->opaqueData); -- Gitee From 59363f63a579605e262a8ee3d145049d5ea485cf Mon Sep 17 00:00:00 2001 From: YangWeimin Date: Thu, 29 May 2025 11:01:28 +0800 Subject: [PATCH 5/6] solve some spelling problem Signed-off-by: YangWeimin --- .../js/napi/http/async_context/src/request_context.cpp | 4 ++-- utils/http_over_curl/src/http_handover_handler.cpp | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/frameworks/js/napi/http/async_context/src/request_context.cpp b/frameworks/js/napi/http/async_context/src/request_context.cpp index 10ef730b2..6b8e21c75 100755 --- a/frameworks/js/napi/http/async_context/src/request_context.cpp +++ b/frameworks/js/napi/http/async_context/src/request_context.cpp @@ -1048,7 +1048,7 @@ std::string RequestContext::GetPinnedPubkey() const } #ifdef HTTP_HANDOVER_FEATURE -void RequestContext::SetRequestHandOverInfo(inte32_t handOverNum, int32_t handOverReason, double flowControlTime, +void RequestContext::SetRequestHandOverInfo(int32_t handOverNum, int32_t handOverReason, double flowControlTime, bool isRead) { requestHandOverInfo_.handOverNum = handOverNum; @@ -1057,7 +1057,7 @@ void RequestContext::SetRequestHandOverInfo(inte32_t handOverNum, int32_t handOv requestHandOverInfo_.isRead = isRead; } -const ReequestHandOverInfo &RequestContext::GetRequestHandOverInfo() +const RequestHandOverInfo &RequestContext::GetRequestHandOverInfo() { return requestHandOverInfo_; } diff --git a/utils/http_over_curl/src/http_handover_handler.cpp b/utils/http_over_curl/src/http_handover_handler.cpp index 31ad9c672..6090011f4 100644 --- a/utils/http_over_curl/src/http_handover_handler.cpp +++ b/utils/http_over_curl/src/http_handover_handler.cpp @@ -290,8 +290,8 @@ void HttpHandoverHandler::HandOverRequestCallback(std::map Date: Thu, 29 May 2025 16:23:37 +0800 Subject: [PATCH 6/6] modify year Signed-off-by: YangWeimin --- utils/http_over_curl/include/epoll_multi_driver.h | 2 +- utils/http_over_curl/include/epoll_request_handler.h | 2 +- utils/http_over_curl/include/manual_reset_event.h | 2 +- utils/http_over_curl/include/request_info.h | 2 +- utils/http_over_curl/include/transfer_callbacks.h | 2 +- utils/http_over_curl/src/epoll_multi_driver.cpp | 2 +- utils/http_over_curl/src/epoll_request_handler.cpp | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/utils/http_over_curl/include/epoll_multi_driver.h b/utils/http_over_curl/include/epoll_multi_driver.h index 17bdc06e7..e824a54ad 100644 --- a/utils/http_over_curl/include/epoll_multi_driver.h +++ b/utils/http_over_curl/include/epoll_multi_driver.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025 Huawei Device Co., Ltd. + * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/utils/http_over_curl/include/epoll_request_handler.h b/utils/http_over_curl/include/epoll_request_handler.h index 3792c59c6..01a4cb95e 100644 --- a/utils/http_over_curl/include/epoll_request_handler.h +++ b/utils/http_over_curl/include/epoll_request_handler.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025 Huawei Device Co., Ltd. + * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/utils/http_over_curl/include/manual_reset_event.h b/utils/http_over_curl/include/manual_reset_event.h index 1199e0cb2..be59c62bf 100644 --- a/utils/http_over_curl/include/manual_reset_event.h +++ b/utils/http_over_curl/include/manual_reset_event.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025 Huawei Device Co., Ltd. + * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/utils/http_over_curl/include/request_info.h b/utils/http_over_curl/include/request_info.h index 14ad196f5..a6db40b21 100644 --- a/utils/http_over_curl/include/request_info.h +++ b/utils/http_over_curl/include/request_info.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025 Huawei Device Co., Ltd. + * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/utils/http_over_curl/include/transfer_callbacks.h b/utils/http_over_curl/include/transfer_callbacks.h index 3405407cf..0ee990f9a 100644 --- a/utils/http_over_curl/include/transfer_callbacks.h +++ b/utils/http_over_curl/include/transfer_callbacks.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025 Huawei Device Co., Ltd. + * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/utils/http_over_curl/src/epoll_multi_driver.cpp b/utils/http_over_curl/src/epoll_multi_driver.cpp index b7d392e59..3465a8c0c 100644 --- a/utils/http_over_curl/src/epoll_multi_driver.cpp +++ b/utils/http_over_curl/src/epoll_multi_driver.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025 Huawei Device Co., Ltd. + * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/utils/http_over_curl/src/epoll_request_handler.cpp b/utils/http_over_curl/src/epoll_request_handler.cpp index 03f41b498..4242a1245 100644 --- a/utils/http_over_curl/src/epoll_request_handler.cpp +++ b/utils/http_over_curl/src/epoll_request_handler.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025 Huawei Device Co., Ltd. + * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at -- Gitee