1 /*
2  * Copyright (c) 2022 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 #ifndef COMMUNICATIONNETMANAGER_BASE_NETMANAGER_BASE_BASE_ASYNC_WORK_H
17 #define COMMUNICATIONNETMANAGER_BASE_NETMANAGER_BASE_BASE_ASYNC_WORK_H
18 
19 #include <limits>
20 #include <memory>
21 
22 #include <napi/native_api.h>
23 #include <napi/native_common.h>
24 
25 #include "base_context.h"
26 #include "napi_constant.h"
27 #include "napi_utils.h"
28 #include "netmanager_base_log.h"
29 #include "nocopyable.h"
30 
31 namespace OHOS {
32 namespace NetManagerStandard {
33 class BaseAsyncWork final {
34 public:
35     DISALLOW_COPY_AND_MOVE(BaseAsyncWork);
36 
37     BaseAsyncWork() = delete;
38 
ExecAsyncWork(napi_env env, void *data)39     template <class Context, bool (*Executor)(Context *)> static void ExecAsyncWork(napi_env env, void *data)
40     {
41         static_assert(std::is_base_of<BaseContext, Context>::value);
42 
43         (void)env;
44 
45         auto context = reinterpret_cast<Context *>(data);
46         if (context == nullptr || Executor == nullptr) {
47             NETMANAGER_BASE_LOGE("context or Executor is nullptr");
48             return;
49         }
50         context->SetExecOK(Executor(context));
51         /* do not have async executor, execOK should be set in sync work */
52     }
53 
54     template <class Context, napi_value (*Callback)(Context *)>
AsyncWorkCallback(napi_env env, napi_status status, void *data)55     static void AsyncWorkCallback(napi_env env, napi_status status, void *data)
56     {
57         static_assert(std::is_base_of<BaseContext, Context>::value);
58 
59         if ((status != napi_ok) || (data == nullptr)) {
60             return;
61         }
62         if (reinterpret_cast<BaseContext *>(data)->magic_ != BASE_CONTEXT_MAGIC_NUMBER) {
63             NETMANAGER_BASE_LOGE("data has been destructed.");
64             return;
65         }
66         auto baseContext = reinterpret_cast<BaseContext *>(data);
67         if (baseContext->GetDeferred() != baseContext->deferredBack1_ ||
68             baseContext->GetDeferred() != baseContext->deferredBack2_ ||
69             baseContext->GetDeferred() != baseContext->deferredBack3_ ||
70             baseContext->GetDeferred() != baseContext->deferredBack4_) {
71             return;
72         }
73 
74         auto deleter = [](Context *context) { delete context; };
75         std::unique_ptr<Context, decltype(deleter)> context(static_cast<Context *>(data), deleter);
76         size_t argc = 2;
77         napi_value argv[2] = {nullptr};
78         if (context->IsExecOK()) {
79             argv[0] = NapiUtils::GetUndefined(env);
80 
81             if (Callback != nullptr) {
82                 argv[1] = Callback(context.get());
83             } else {
84                 argv[1] = NapiUtils::GetUndefined(env);
85             }
86             if (argv[1] == nullptr) {
87                 NETMANAGER_BASE_LOGE("AsyncWorkName %{public}s createData fail", context->GetAsyncWorkName().c_str());
88                 return;
89             }
90         } else {
91             argv[0] = NapiUtils::CreateErrorMessage(env, context->GetErrorCode(), context->GetErrorMessage());
92             if (argv[0] == nullptr) {
93                 NETMANAGER_BASE_LOGE("AsyncWorkName %{public}s createErrorMessage fail",
94                                      context->GetAsyncWorkName().c_str());
95                 return;
96             }
97 
98             argv[1] = NapiUtils::GetUndefined(env);
99         }
100 
101         if (context->GetDeferred() != nullptr) {
102             if (context->IsExecOK()) {
103                 napi_resolve_deferred(env, context->GetDeferred(), argv[1]);
104             } else {
105                 napi_reject_deferred(env, context->GetDeferred(), argv[0]);
106             }
107             return;
108         }
109 
110         napi_value func = context->GetCallback();
111         napi_value undefined = NapiUtils::GetUndefined(env);
112         (void)NapiUtils::CallFunction(env, undefined, func, argc, argv);
113     }
114 
115     template <class Context, napi_value (*Callback)(Context *)>
AsyncWorkCallbackForSystem(napi_env env, napi_status status, void *data)116     static void AsyncWorkCallbackForSystem(napi_env env, napi_status status, void *data)
117     {
118         static_assert(std::is_base_of<BaseContext, Context>::value);
119 
120         if ((status != napi_ok) || (data == nullptr)) {
121             return;
122         }
123         auto deleter = [](Context *context) { delete context; };
124         std::unique_ptr<Context, decltype(deleter)> context(static_cast<Context *>(data), deleter);
125         if (Callback != nullptr) {
126             (void)Callback(context.get());
127         }
128     }
129 };
130 } // namespace NetManagerStandard
131 } // namespace OHOS
132 
133 #endif // COMMUNICATIONNETMANAGER_BASE_NETMANAGER_BASE_BASE_ASYNC_WORK_H
134