diff --git a/bundle.json b/bundle.json index 38c6b7a5038587abd5f4b151318ed7fb37c5433a..64fcbdafb9a7a2dd3bb91d0cc9016a0ec6a70807 100644 --- a/bundle.json +++ b/bundle.json @@ -57,6 +57,8 @@ "libwebsockets", "node", "jsoncpp", + "netmanager_enhanced", + "common_event_service", "access_token", "hiappevent", "bundle_framework", diff --git a/frameworks/js/napi/http/BUILD.gn b/frameworks/js/napi/http/BUILD.gn index ecca6f01a171360dead51d2d7542ef347bf89279..c135e0a92c2a423662eb0851506e33932abe7265 100644 --- a/frameworks/js/napi/http/BUILD.gn +++ b/frameworks/js/napi/http/BUILD.gn @@ -146,6 +146,7 @@ ohos_shared_library("http") { "napi:ace_napi", "samgr:samgr_proxy", "time_service:time_client", + "common_event_service:cesfwk_innerkits", ] external_deps += [ 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 2e0453259227388c63570ee26cd38dd392105825..88cf95f68bf83f874b82d9ec31e177ed04621234 100644 --- a/frameworks/js/napi/http/async_context/include/request_context.h +++ b/frameworks/js/napi/http/async_context/include/request_context.h @@ -169,6 +169,10 @@ public: std::string GetPinnedPubkey() const; + void SetDelayTime(int64_t delayTime); + + int64_t GetDelayTime(); + #ifdef HTTP_HANDOVER_FEATURE void SetRequestHandoverInfo(int32_t handoverNum, int32_t handoverReason, double flowControlTime, int32_t readFlag); @@ -177,6 +181,7 @@ public: private: uint32_t magicNumber_ = MAGIC_NUMBER; int32_t taskId_ = -1; + int64_t delayTime_ = 0L; bool usingCache_ = true; bool requestInStream_ = false; std::mutex dlLenLock_; 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 fc6e37871aea8f984446ef90d246036ad1fa3d3c..f5003f71ecc4f23288421db4f5e6ce5d63e08515 100755 --- a/frameworks/js/napi/http/async_context/src/request_context.cpp +++ b/frameworks/js/napi/http/async_context/src/request_context.cpp @@ -1097,4 +1097,14 @@ void RequestContext::ParseAddressFamily(napi_value optionsValue) options.SetAddressFamily(addressFamily); } } + +void RequestContext::SetDelayTime(int64_t delayTime) +{ + delayTime_ = delayTime; +} + +int64_t RequestContext::GetDelayTime() +{ + return delayTime_; +} } // namespace OHOS::NetStack::Http diff --git a/frameworks/js/napi/http/http_exec/include/http_exec.h b/frameworks/js/napi/http/http_exec/include/http_exec.h index 6b0ca2af6731ee52cdbe09854fdb8b349596645d..8c74d6aed8891da99c153ca1f601c8188ed5686f 100644 --- a/frameworks/js/napi/http/http_exec/include/http_exec.h +++ b/frameworks/js/napi/http/http_exec/include/http_exec.h @@ -33,6 +33,10 @@ #include "napi/native_api.h" #include "request_context.h" +#include "common_event_manager.h" +#include "common_event_support.h" +#include "want.h" + namespace OHOS::NetStack::HttpOverCurl { struct TransferCallbacks; } @@ -91,6 +95,16 @@ public: static void AsyncRunRequest(RequestContext *context); + static void RunRequestWithDelayTime(RequestContext *context); + + static void SendNewEarlyExecTime(int64_t earlyExecTime, int64_t delayTime); + + static void HandleCtrlStatusChanged(bool ctrlStatus); + + static void SubscribeCommonEvent(); + + static int64_t CalEarlyExecTime(int64_t delayTime); + private: static bool SetOption(CURL *curl, RequestContext *context, struct curl_slist *requestHeader); @@ -237,6 +251,37 @@ private: }; static StaticVariable staticVariable_; #endif + + static bool isControl_; + + static std::mutex mtx; + + struct RequestTask { + RequestContext* context_; + int64_t earlyExecTime_; + int64_t delayTime_; + + RequestTask(RequestContext* context, int64_t earlyExecTime, int64_t delayTime) + : context_(context), earlyExecTime_(earlyExecTime), delayTime_(delayTime) {} + }; + + struct ControlCompare { + bool operator()(const RequestTask& a, const RequestTask& b) const + { + return a.earlyExecTime_ > b.earlyExecTime_; + } + }; + + static std::priority_queue, ControlCompare> controlQueue_; + + class ControlEventSubscriber : public OHOS::EventFwk::CommonEventSubscriber { + public: + explicit ControlEventSubscriber(const OHOS::EventFwk::CommonEventSubscribeInfo &subscribeInfo) + : OHOS::EventFwk::CommonEventSubscriber(subscribeInfo) {}; + virtual void OnReceiveEvent(const OHOS::EventFwk::CommonEventData &eventData) override; + }; + + static std::shared_ptr controlEventSubscriber_; }; } // namespace OHOS::NetStack::Http 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 5c35b5a8187baa5b63bb093ccdde80f78fe86acd..b41439834361251e54c79b97dec2630e8e3a9528 100755 --- a/frameworks/js/napi/http/http_exec/src/http_exec.cpp +++ b/frameworks/js/napi/http/http_exec/src/http_exec.cpp @@ -86,6 +86,12 @@ } while (0) namespace OHOS::NetStack::Http { +bool HttpExec::isControl_ = true; +std::mutex HttpExec::mtx; +std::priority_queue, + HttpExec::ControlCompare> HttpExec::controlQueue_; +std::shared_ptr HttpExec::controlEventSubscriber_; + #if !HAS_NETMANAGER_BASE static constexpr int CURL_TIMEOUT_MS = 20; static constexpr int CONDITION_TIMEOUT_S = 3600; @@ -124,6 +130,8 @@ 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"; +static constexpr const char *COMMON_EVENT_CONTROL_STATUS = "usual.event.NET_CTRL_STATUS"; +static constexpr const char *COMMON_EVENT_SEND_EARLY_EXEC_TIME = "usual.event.SEND_EARLY_EXEC_TIME"; static int64_t g_limitSdkReport = 0; static void RequestContextDeleter(RequestContext *context) @@ -974,6 +982,8 @@ bool HttpExec::Initialize() return false; } + SubscribeCommonEvent(); + staticVariable_.workThread = std::thread(RunThread); staticVariable_.initialized = true; return staticVariable_.initialized; @@ -1900,6 +1910,91 @@ void HttpExec::AsyncRunRequest(RequestContext *context) HttpAsyncWork::ExecRequest(context->GetEnv(), context); } +void HttpExec::RunRequestWithDelayTime(RequestContext *context) +{ + if (context->GetDelayTime() == 0 || !isControl_) { + NETSTACK_LOGI("Cur request is urgent, or cur ctrl status is release"); + AsyncRunRequest(context); + return; + } + + auto delayTime = context->GetDelayTime(); + auto curEarlyExecTime = CalEarlyExecTime(delayTime); + RequestTask reqTask(context, curEarlyExecTime, delayTime); + + std::unique_lock lock(mtx); + if (controlQueue_.empty()) { + controlQueue_.push(reqTask); + SendNewEarlyExecTime(curEarlyExecTime, delayTime); + return; + } + + auto earlyExecTime = controlQueue_.top().earlyExecTime_; + controlQueue_.push(reqTask); + lock.unlock(); + + if (curEarlyExecTime >= earlyExecTime) { + return; + } + SendNewEarlyExecTime(curEarlyExecTime, delayTime); +} + +void HttpExec::SendNewEarlyExecTime(int64_t earlyExecTime, int64_t delayTime) +{ + OHOS::EventFwk::CommonEventData data; + AAFwk::Want want; + want.SetAction(COMMON_EVENT_SEND_EARLY_EXEC_TIME); + want.SetParam("earlyExecTime", earlyExecTime); + want.SetParam("delayTime", delayTime); + data.SetWant(want); + OHOS::EventFwk::CommonEventPublishInfo publishInfo; + OHOS::EventFwk::CommonEventManager::PublishCommonEvent(data, publishInfo); +} + +void HttpExec::HandleCtrlStatusChanged(bool ctrlStatus) +{ + isControl_ = ctrlStatus; + if (isControl_) { + return; + } + + std::unique_lock lock(mtx); + while (!controlQueue_.empty()) { + AsyncRunRequest(controlQueue_.top().context_); + controlQueue_.pop(); + } +} + +void HttpExec::SubscribeCommonEvent() +{ + EventFwk::MatchingSkills matchingSkills; + matchingSkills.AddEvent(COMMON_EVENT_CONTROL_STATUS); + EventFwk::CommonEventSubscribeInfo subscribeInfo(matchingSkills); + controlEventSubscriber_ = std::make_shared(subscribeInfo); + bool ret = EventFwk::CommonEventManager::SubscribeCommonEvent(controlEventSubscriber_); + if (!ret) { + NETSTACK_LOGE("Subscribe control event fail:%{public}d", ret); + } +} + +void HttpExec::ControlEventSubscriber::OnReceiveEvent(const EventFwk::CommonEventData &eventData) +{ + const auto &action = eventData.GetWant().GetAction(); + if (action != COMMON_EVENT_CONTROL_STATUS) { + return; + } + + const auto ctrlStatus = eventData.GetWant().GetBoolParam("ctrlStatus", false); + HandleCtrlStatusChanged(ctrlStatus); +} + +int64_t HttpExec::CalEarlyExecTime(int64_t delayTime) +{ + auto earlyExecTimePoint = std::chrono::system_clock::now() + std::chrono::seconds(delayTime); + auto earlyExecTimeMillisecond = std::chrono::time_point_cast(earlyExecTimePoint); + return earlyExecTimeMillisecond.time_since_epoch().count(); +} + #if !HAS_NETMANAGER_BASE bool HttpExec::IsInitialized() { diff --git a/frameworks/js/napi/http/http_module/include/http_module.h b/frameworks/js/napi/http/http_module/include/http_module.h index 9f16542cdb637aa27d83ebdae47e1097a94865a2..2912c3b37ee18935d4d92776f7820feadde80677 100644 --- a/frameworks/js/napi/http/http_module/include/http_module.h +++ b/frameworks/js/napi/http/http_module/include/http_module.h @@ -40,6 +40,7 @@ public: static constexpr const char *FUNCTION_OFF = "off"; static napi_value Request(napi_env env, napi_callback_info info); + static napi_value RequestWithDelayTime(napi_env env, napi_callback_info info); static napi_value RequestInStream(napi_env env, napi_callback_info info); static napi_value Destroy(napi_env env, napi_callback_info info); static napi_value On(napi_env env, napi_callback_info info); diff --git a/frameworks/js/napi/http/http_module/src/http_module.cpp b/frameworks/js/napi/http/http_module/src/http_module.cpp index c32614bdcca5d4036974c4784914ba434e7eaeec..21109e01af18a914b3c0f5c14546e11d3ae40c3a 100644 --- a/frameworks/js/napi/http/http_module/src/http_module.cpp +++ b/frameworks/js/napi/http/http_module/src/http_module.cpp @@ -285,6 +285,25 @@ napi_value HttpModuleExports::HttpRequest::Request(napi_env env, napi_callback_i "Request", HttpAsyncWork::ExecRequest, HttpAsyncWork::RequestCallback); } +napi_value HttpModuleExports::HttpRequest::RequestWithDelayTime(napi_env env, napi_callback_info info) +{ + return ModuleTemplate::InterfaceWithOutAsyncWorkWithManagerWrapper( + env, info, + [](napi_env, napi_value, RequestContext *context) -> bool { +#if !HAS_NETMANAGER_BASE + if (!HttpExec::Initialize()) { + return false; + } +#endif + context->SetModuleId(g_moduleId); + context->SetAtomicService(g_appIsAtomicService); + context->SetBundleName(g_appBundleName); + HttpExec::RunRequestWithDelayTime(context); + return context->IsExecOK(); + }, + "Request", HttpAsyncWork::ExecRequest, HttpAsyncWork::RequestCallback); +} + napi_value HttpModuleExports::HttpRequest::RequestInStream(napi_env env, napi_callback_info info) { return ModuleTemplate::InterfaceWithOutAsyncWorkWithManagerWrapper( diff --git a/frameworks/js/napi/socket/BUILD.gn b/frameworks/js/napi/socket/BUILD.gn index c2754c7dcc0f8bb2072e15d04e2f5d4b8512dc74..3e563ed7de5df55b404e968f1d5e1b3ff3af8d69 100644 --- a/frameworks/js/napi/socket/BUILD.gn +++ b/frameworks/js/napi/socket/BUILD.gn @@ -144,6 +144,7 @@ ohos_shared_library("socket") { "openssl:libcrypto_shared", "openssl:libssl_shared", "samgr:samgr_proxy", + "common_event_service:cesfwk_innerkits", ] if (!build_ohos_sdk) { diff --git a/frameworks/js/napi/socket/async_context/include/tcp_send_context.h b/frameworks/js/napi/socket/async_context/include/tcp_send_context.h index c9c852535e63e67f8875494ddfb4b4a002ac79fb..f52040ea940c19040420a7a99e489d4493b4624f 100644 --- a/frameworks/js/napi/socket/async_context/include/tcp_send_context.h +++ b/frameworks/js/napi/socket/async_context/include/tcp_send_context.h @@ -44,10 +44,16 @@ public: TCPSendOptions options; + void SetDelayTime(int64_t delayTime); + + int64_t GetDelayTime(); + private: bool CheckParamsType(napi_value *params, size_t paramsCount); bool GetData(napi_value udpSendOptions); + + int64_t delayTime_; }; } // namespace OHOS::NetStack::Socket diff --git a/frameworks/js/napi/socket/async_context/include/udp_send_context.h b/frameworks/js/napi/socket/async_context/include/udp_send_context.h index 432a931892bf4d6457875583b111cde930922451..23f401a3592bdfdde115d545c354551eaded4de4 100644 --- a/frameworks/js/napi/socket/async_context/include/udp_send_context.h +++ b/frameworks/js/napi/socket/async_context/include/udp_send_context.h @@ -46,12 +46,17 @@ public: std::shared_ptr proxyOptions{nullptr}; + void SetDelayTime(int64_t delayTime); + + int64_t GetDelayTime(); private: bool CheckParamsType(napi_value *params, size_t paramsCount); bool GetData(napi_value udpSendOptions); void HandleCallback(napi_value *params, size_t paramsCount); + + int64_t delayTime_; }; } // namespace OHOS::NetStack::Socket diff --git a/frameworks/js/napi/socket/async_context/src/tcp_send_context.cpp b/frameworks/js/napi/socket/async_context/src/tcp_send_context.cpp index 02eb09536f2acbc5cc36841431b064c9cdcc8789..9f05ffb76a5c1eac0996558f21bec64795cbecd0 100644 --- a/frameworks/js/napi/socket/async_context/src/tcp_send_context.cpp +++ b/frameworks/js/napi/socket/async_context/src/tcp_send_context.cpp @@ -142,4 +142,14 @@ std::string TcpSendContext::GetErrorMessage() const return err; #endif } + +void TcpSendContext::SetDelayTime(int64_t delayTime) +{ + delayTime_ = delayTime; +} + +int64_t TcpSendContext::GetDelayTime() +{ + return delayTime_; +} } // namespace OHOS::NetStack::Socket diff --git a/frameworks/js/napi/socket/async_context/src/udp_send_context.cpp b/frameworks/js/napi/socket/async_context/src/udp_send_context.cpp index b5f9a3cdd78940f616d766e91d98046e4e8016b8..c40a2f49809b25277510dab077792fcd31fa60c0 100644 --- a/frameworks/js/napi/socket/async_context/src/udp_send_context.cpp +++ b/frameworks/js/napi/socket/async_context/src/udp_send_context.cpp @@ -186,4 +186,14 @@ std::string UdpSendContext::GetErrorMessage() const return err; #endif } + +void UdpSendContext::SetDelayTime(int64_t delayTime) +{ + delayTime_ = delayTime; +} + +int64_t UdpSendContext::GetDelayTime() +{ + return delayTime_; +} } // namespace OHOS::NetStack::Socket diff --git a/frameworks/js/napi/socket/async_work/include/socket_async_work.h b/frameworks/js/napi/socket/async_work/include/socket_async_work.h index 1f4848a620dc4e6ec9b3d9ec1ad90014705f7ecb..5ecdd56cdd2a17b60a541d14ca0fdbe84c8ac5a4 100644 --- a/frameworks/js/napi/socket/async_work/include/socket_async_work.h +++ b/frameworks/js/napi/socket/async_work/include/socket_async_work.h @@ -29,6 +29,8 @@ public: static void ExecUdpSend(napi_env env, void *data); + static void ExecUdpSendWithDelayTime(napi_env env, void *data); + static void ExecUdpAddMembership(napi_env env, void *data); static void ExecUdpDropMembership(napi_env env, void *data); @@ -47,6 +49,8 @@ public: static void ExecTcpSend(napi_env env, void *data); + static void ExecTcpSendWithDelayTime(napi_env env, void *data); + static void ExecClose(napi_env env, void *data); static void ExecGetState(napi_env env, void *data); diff --git a/frameworks/js/napi/socket/async_work/src/socket_async_work.cpp b/frameworks/js/napi/socket/async_work/src/socket_async_work.cpp index 8dd23641a28bd99106d4063731a211075201582a..149f2dd2da43f04d5aade913b9ca8805cef9034d 100644 --- a/frameworks/js/napi/socket/async_work/src/socket_async_work.cpp +++ b/frameworks/js/napi/socket/async_work/src/socket_async_work.cpp @@ -48,6 +48,11 @@ void SocketAsyncWork::ExecUdpSend(napi_env env, void *data) BaseAsyncWork::ExecAsyncWork(env, data); } +void SocketAsyncWork::ExecUdpSendWithDelayTime(napi_env env, void *data) +{ + BaseAsyncWork::ExecAsyncWork(env, data); +} + void SocketAsyncWork::ExecUdpAddMembership(napi_env env, void *data) { BaseAsyncWork::ExecAsyncWork(env, data); @@ -98,6 +103,11 @@ void SocketAsyncWork::ExecTcpSend(napi_env env, void *data) BaseAsyncWork::ExecAsyncWork(env, data); } +void SocketAsyncWork::ExecTcpSendWithDelayTime(napi_env env, void *data) +{ + BaseAsyncWork::ExecAsyncWork(env, data); +} + void SocketAsyncWork::ExecGetState(napi_env env, void *data) { BaseAsyncWork::ExecAsyncWork(env, data); diff --git a/frameworks/js/napi/socket/socket_exec/include/socket_exec.h b/frameworks/js/napi/socket/socket_exec/include/socket_exec.h index d545af8b705b49565ebd24b36eadd2559444c6b1..9cb6cc65defa53097f44022744045230dfe40169 100644 --- a/frameworks/js/napi/socket/socket_exec/include/socket_exec.h +++ b/frameworks/js/napi/socket/socket_exec/include/socket_exec.h @@ -34,6 +34,9 @@ #include "udp_extra_context.h" #include "udp_send_context.h" #include "napi_utils.h" +#include "common_event_manager.h" +#include "common_event_support.h" +#include "want.h" #include @@ -45,6 +48,8 @@ bool ExecUdpBind(BindContext *context); bool ExecUdpSend(UdpSendContext *context); +bool ExecUdpSendWithDelayTime(UdpSendContext *context); + bool ExecUdpAddMembership(MulticastMembershipContext *context); bool ExecUdpDropMembership(MulticastMembershipContext *context); @@ -63,6 +68,8 @@ bool ExecConnect(ConnectContext *context); bool ExecTcpSend(TcpSendContext *context); +bool ExecTcpSendWithDelayTime(TcpSendContext *context); + bool ExecClose(CloseContext *context); bool ExecGetState(GetStateContext *context); @@ -97,6 +104,14 @@ bool ExecTcpServerGetState(TcpServerGetStateContext *context); bool ExecTcpServerGetLocalAddress(TcpServerGetLocalAddressContext *context); +void SendNewEarlyExecTime(int64_t earlyExecTime, int64_t delayTime); + +void HandleCtrlStatusChanged(bool ctrlStatus); + +void SubscribeCommonEvent(); + +int64_t CalEarlyExecTime(int64_t delayTime); + /* async work callback */ napi_value BindCallback(BindContext *context); @@ -277,5 +292,37 @@ protected: using SocketRecvCallback = std::function &, int> &bufInfo, std::pair &addrInfo, const MessageCallback &callback)>; +static bool isControl_; + +struct DataSendTask { + TcpSendContext* tcpContext_; + UdpSendContext* udpContext_; + int64_t earlyExecTime_; + int64_t delayTime_; + + DataSendTask(TcpSendContext* context, int64_t earlyExecTime, int64_t delayTime) + : tcpContext_(context), earlyExecTime_(earlyExecTime), delayTime_(delayTime) {} + + DataSendTask(UdpSendContext* context, int64_t earlyExecTime, int64_t delayTime) + : udpContext_(context), earlyExecTime_(earlyExecTime), delayTime_(delayTime) {} +}; + +struct ControlCompare { + bool operator()(const DataSendTask& a, const DataSendTask& b) const + { + return a.earlyExecTime_ > b.earlyExecTime_; + } +}; + +static std::priority_queue, ControlCompare> controlQueue_; + +class ControlEventSubscriber : public OHOS::EventFwk::CommonEventSubscriber { +public: + explicit ControlEventSubscriber(const OHOS::EventFwk::CommonEventSubscribeInfo &subscribeInfo) + : OHOS::EventFwk::CommonEventSubscriber(subscribeInfo) {}; + virtual void OnReceiveEvent(const OHOS::EventFwk::CommonEventData &eventData) override; +}; + +static std::shared_ptr controlEventSubscriber_; } // namespace OHOS::NetStack::Socket::SocketExec #endif /* COMMUNICATIONNETSTACK_SOCKET_EXEC_H */ diff --git a/frameworks/js/napi/socket/socket_exec/src/socket_exec.cpp b/frameworks/js/napi/socket/socket_exec/src/socket_exec.cpp index 7d93a2842f64b76f3b36022f328a180e79cdebd4..decb9f64ff3aee0ce18cd4e49c9288182640a3c8 100644 --- a/frameworks/js/napi/socket/socket_exec/src/socket_exec.cpp +++ b/frameworks/js/napi/socket/socket_exec/src/socket_exec.cpp @@ -86,6 +86,10 @@ static constexpr const char *SOCKET_RECV_FROM_MULTI_CAST = "OS_NET_SockMPRD"; static constexpr const char *WILD_ADDRESS = "0.0.0.0"; +static constexpr const char *COMMON_EVENT_CONTROL_STATUS = "usual.event.CONTROL_STATUS"; + +static constexpr const char *COMMON_EVENT_SEND_EARLY_EXEC_TIME = "usual.event.SEND_EARLY_EXEC_TIME"; + namespace OHOS::NetStack::Socket::SocketExec { #define ERROR_RETURN(context, ...) \ do { \ @@ -100,6 +104,7 @@ std::map> g_clientEventManagers; std::condition_variable g_cv; std::mutex g_mutex; std::shared_mutex g_fdMutex; +std::mutex g_queueMutex; std::atomic_int g_userCounter = 0; static void SetIsBound(sa_family_t family, GetStateContext *context, const sockaddr_in *addr4, @@ -1082,6 +1087,38 @@ bool ExecUdpSend(UdpSendContext *context) return result; } +bool ExecUdpSendWithDelayTime(UdpSendContext *context) +{ + if (context == nullptr) { + return false; + } + if (context->GetDelayTime() == 0 || !isControl_) { + ExecUdpSend(context); + return true; + } + + auto delayTime = context->GetDelayTime(); + auto curEarlyExecTime = CalEarlyExecTime(delayTime); + DataSendTask dataSendTask(context, curEarlyExecTime, delayTime); + + std::unique_lock lock(g_queueMutex); + if (controlQueue_.empty()) { + controlQueue_.push(dataSendTask); + SendNewEarlyExecTime(curEarlyExecTime, delayTime); + return true; + } + + auto earlyExecTime = controlQueue_.top().earlyExecTime_; + controlQueue_.push(dataSendTask); + lock.unlock(); + + if (curEarlyExecTime >= earlyExecTime) { + return true; + } + SendNewEarlyExecTime(curEarlyExecTime, delayTime); + return true; +} + bool ExecTcpBind(BindContext *context) { return ExecBind(context); @@ -1242,6 +1279,38 @@ bool ExecTcpSend(TcpSendContext *context) return result; } +bool ExecTcpSendWithDelayTime(TcpSendContext *context) +{ + if (context == nullptr) { + return false; + } + if (context->GetDelayTime() == 0 || !isControl_) { + ExecTcpSend(context); + return true; + } + + auto delayTime = context->GetDelayTime(); + auto curEarlyExecTime = CalEarlyExecTime(delayTime); + DataSendTask dataSendTask(context, curEarlyExecTime, delayTime); + + std::unique_lock lock(g_queueMutex); + if (controlQueue_.empty()) { + controlQueue_.push(dataSendTask); + SendNewEarlyExecTime(curEarlyExecTime, delayTime); + return true; + } + + auto earlyExecTime = controlQueue_.top().earlyExecTime_; + controlQueue_.push(dataSendTask); + lock.unlock(); + + if (curEarlyExecTime >= earlyExecTime) { + return true; + } + SendNewEarlyExecTime(curEarlyExecTime, delayTime); + return true; +} + bool ExecClose(CloseContext *context) { if (!CommonUtils::HasInternetPermission()) { @@ -2431,6 +2500,67 @@ bool ExecTcpServerGetState(TcpServerGetStateContext *context) return GetTcpServerState(context); } +void SendNewEarlyExecTime(int64_t earlyExecTime, int64_t delayTime) +{ + OHOS::EventFwk::CommonEventData data; + AAFwk::Want want; + want.SetAction(COMMON_EVENT_SEND_EARLY_EXEC_TIME); + want.SetParam("earlyExecTime", earlyExecTime); + want.SetParam("delayTime", delayTime); + data.SetWant(want); + OHOS::EventFwk::CommonEventPublishInfo publishInfo; + EventFwk::CommonEventManager::PublishCommonEvent(data, publishInfo); +} + +void HandleCtrlStatusChanged(bool ctrlStatus) +{ + isControl_ = ctrlStatus; + if (isControl_) { + return; + } + + std::unique_lock lock(g_queueMutex); + while (!controlQueue_.empty()) { + auto data = controlQueue_.top(); + if (data.tcpContext_ != nullptr) { + ExecTcpSend(data.tcpContext_); + } else if (data.udpContext_ != nullptr) { + ExecUdpSend(data.udpContext_); + } + controlQueue_.pop(); + } +} + +void SubscribeCommonEvent() +{ + EventFwk::MatchingSkills matchingSkills; + matchingSkills.AddEvent(COMMON_EVENT_CONTROL_STATUS); + EventFwk::CommonEventSubscribeInfo subscribeInfo(matchingSkills); + controlEventSubscriber_ = std::make_shared(subscribeInfo); + bool ret = EventFwk::CommonEventManager::SubscribeCommonEvent(controlEventSubscriber_); + if (!ret) { + NETSTACK_LOGE("Subscribe control event fail:%{public}d", ret); + } +} + +void ControlEventSubscriber::OnReceiveEvent(const EventFwk::CommonEventData &eventData) +{ + const auto &action = eventData.GetWant().GetAction(); + if (action != COMMON_EVENT_CONTROL_STATUS) { + return; + } + + const auto ctrlStatus = eventData.GetWant().GetBoolParam("ctrlStatus", false); + HandleCtrlStatusChanged(ctrlStatus); +} + +int64_t CalEarlyExecTime(int64_t delayTime) +{ + auto earlyExecTimePoint = std::chrono::system_clock::now() + std::chrono::seconds(delayTime); + auto earlyExecTimeMillisecond = std::chrono::time_point_cast(earlyExecTimePoint); + return earlyExecTimeMillisecond.time_since_epoch().count(); +} + napi_value BindCallback(BindContext *context) { context->EmitSharedManager(EVENT_LISTENING, std::make_pair(NapiUtils::GetUndefined(context->GetEnv()), diff --git a/frameworks/js/napi/socket/socket_module/include/socket_module.h b/frameworks/js/napi/socket/socket_module/include/socket_module.h index 6d31bea01b817d7bded1bbf4cabd959072fa4f2c..92d7a8d7ac79a74c05bdafe07e9c3281cdd8109a 100644 --- a/frameworks/js/napi/socket/socket_module/include/socket_module.h +++ b/frameworks/js/napi/socket/socket_module/include/socket_module.h @@ -35,6 +35,7 @@ public: static napi_value Bind(napi_env env, napi_callback_info info); static napi_value Send(napi_env env, napi_callback_info info); + static napi_value SendWithDelayTime(napi_env env, napi_callback_info info); static napi_value Close(napi_env env, napi_callback_info info); static napi_value GetState(napi_env env, napi_callback_info info); static napi_value GetLocalAddress(napi_env env, napi_callback_info info); @@ -142,6 +143,7 @@ public: static napi_value Bind(napi_env env, napi_callback_info info); static napi_value Connect(napi_env env, napi_callback_info info); static napi_value Send(napi_env env, napi_callback_info info); + static napi_value SendWithDelayTime(napi_env env, napi_callback_info info); static napi_value Close(napi_env env, napi_callback_info info); static napi_value GetRemoteAddress(napi_env env, napi_callback_info info); static napi_value GetLocalAddress(napi_env env, napi_callback_info info); diff --git a/frameworks/js/napi/socket/socket_module/src/socket_module.cpp b/frameworks/js/napi/socket/socket_module/src/socket_module.cpp index 115197967553056ce39576b690258b9227cca4ae..6f12d58b446e7ffcd14cb5f09f46fe143dbcdeca 100644 --- a/frameworks/js/napi/socket/socket_module/src/socket_module.cpp +++ b/frameworks/js/napi/socket/socket_module/src/socket_module.cpp @@ -673,6 +673,17 @@ napi_value SocketModuleExports::UDPSocket::Send(napi_env env, napi_callback_info UDP_SEND_NAME, SocketAsyncWork::ExecUdpSend, SocketAsyncWork::UdpSendCallback); } +napi_value SocketModuleExports::UDPSocket::SendWithDelayTime(napi_env env, napi_callback_info info) +{ + return ModuleTemplate::InterfaceWithOutAsyncWorkWithSharedManager( + env, info, + [](napi_env, napi_value, UdpSendContext *context) -> bool { + SocketAsyncWork::ExecUdpSendWithDelayTime(context->GetEnv(), context); + return true; + }, + UDP_SEND_NAME, SocketAsyncWork::ExecUdpSend, SocketAsyncWork::UdpSendCallback); +} + napi_value SocketModuleExports::UDPSocket::Close(napi_env env, napi_callback_info info) { return SOCKET_INTERFACE(CloseContext, ExecClose, CloseCallback, nullptr, UDP_CLOSE_NAME); @@ -776,6 +787,17 @@ napi_value SocketModuleExports::TCPSocket::Send(napi_env env, napi_callback_info TCP_SEND_NAME, SocketAsyncWork::ExecTcpSend, SocketAsyncWork::TcpSendCallback); } +napi_value SocketModuleExports::TCPSocket::SendWithDelayTime(napi_env env, napi_callback_info info) +{ + return ModuleTemplate::InterfaceWithOutAsyncWorkWithSharedManager( + env, info, + [](napi_env, napi_value, TcpSendContext *context) -> bool { + SocketAsyncWork::ExecTcpSendWithDelayTime(context->GetEnv(), context); + return true; + }, + TCP_SEND_NAME, SocketAsyncWork::ExecTcpSend, SocketAsyncWork::TcpSendCallback); +} + napi_value SocketModuleExports::TCPSocket::Close(napi_env env, napi_callback_info info) { return SOCKET_INTERFACE(CloseContext, ExecClose, CloseCallback, nullptr, TCP_CLOSE_NAME);