1 /*
2 * Copyright (c) 2025 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 "net_conn_client.h"
17 #include <ani.h>
18 #include <array>
19 #include <cstdint>
20 #include <iostream>
21 #include <string>
22 #include <vector>
23
24 static const int32_t ANI_ERROR_CODE = 3;
25
26 constexpr const char *NET_HANDLE_INNER = "L@ohos/net/connection/connection/NetHandleInner;";
27 constexpr const char *BUSINESS_ERROR = "L@ohos/base/BusinessError;";
28 constexpr const char *CTOR = "<ctor>";
29
30 static const std::unordered_map<int32_t, std::string> errorMap = {
31 {201, "Permission denied."},
32 {2100002, "Failed to connect to the service."},
33 {2100003, "System internal error."},
34 };
35
ANIUtils_StdStringToANIString(ani_env * env,std::string str)36 ani_string ANIUtils_StdStringToANIString(ani_env *env, std::string str)
37 {
38 ani_string result_string{};
39 env->String_NewUTF8(str.c_str(), str.size(), &result_string);
40 return result_string;
41 }
42
GetClass(ani_env * env,const char * className)43 ani_class GetClass(ani_env *env, const char *className)
44 {
45 ani_class cls;
46 if (ANI_OK != env->FindClass(className, &cls)) {
47 std::cerr << "Not found '" << className << "'" << std::endl;
48 }
49 return cls;
50 }
GetMethod(ani_env * env,ani_class cls,const char * methodName,const char * methodSignature)51 ani_method GetMethod(ani_env *env, ani_class cls, const char *methodName, const char *methodSignature)
52 {
53 ani_method method;
54 if (ANI_OK != env->Class_FindMethod(cls, methodName, methodSignature, &method)) {
55 std::cerr << "Not found method '" << methodName << methodSignature << "'" << std::endl;
56 }
57 return method;
58 }
59
ObjectNew(ani_env * env,const char * className,const char * methodSignature)60 ani_object ObjectNew(ani_env *env, const char *className, const char *methodSignature)
61 {
62 ani_class cls = GetClass(env, className);
63 ani_method ctor = GetMethod(env, cls, CTOR, methodSignature);
64 ani_object result;
65 env->Object_New(cls, ctor, &result);
66 return result;
67 }
68
throwBusinessError(ani_env * env,int32_t code,std::string & msg)69 void throwBusinessError(ani_env *env, int32_t code, std::string &msg)
70 {
71 ani_class businessError = GetClass(env, BUSINESS_ERROR);
72 ani_method businessErrorCtor = GetMethod(env, businessError, CTOR, "DLescompat/Error;:V");
73 ani_class errorcls = GetClass(env, "Lescompat/Error;");
74 ani_method ctor = GetMethod(env, errorcls, CTOR, "Lstd/core/String;:V");
75 ani_string errorMsg = ANIUtils_StdStringToANIString(env, msg);
76
77 ani_object errorObj;
78 env->Object_New(errorcls, ctor, &errorObj, errorMsg);
79
80 ani_object businessErrorObj;
81 env->Object_New(businessError, businessErrorCtor, &businessErrorObj, errorObj);
82 env->ThrowError(static_cast<ani_error>(businessErrorObj));
83 }
84
getDefaultNetSync(ani_env * env)85 static ani_object getDefaultNetSync([[maybe_unused]] ani_env *env)
86 {
87 OHOS::NetManagerStandard::NetHandle nethandle;
88 int32_t ret = OHOS::NetManagerStandard::NetConnClient::GetInstance().GetDefaultNet(nethandle);
89 if (ret == 0) {
90 ani_object nethandleInner = ObjectNew(env, NET_HANDLE_INNER, nullptr);
91 ani_class cls = GetClass(env, NET_HANDLE_INNER);
92 ani_method setter = GetMethod(env, cls, "<set>netId", nullptr);
93 env->Object_CallMethod_Void(nethandleInner, setter, ani_double(nethandle.GetNetId()));
94 return nethandleInner;
95 } else {
96 ani_ref undefined;
97 env->GetUndefined(&undefined);
98
99 std::string msg;
100 auto it = errorMap.find(ret);
101 if (it != errorMap.end()) {
102 msg = it->second;
103 } else {
104 msg = "Unknown error.";
105 }
106 throwBusinessError(env, ret, msg);
107 return static_cast<ani_object>(undefined);
108 }
109 }
110
ANI_Constructor(ani_vm * vm,uint32_t * result)111 ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result)
112 {
113 ani_env *env;
114 if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) {
115 std::cerr << "Unsupported ANI_VERSION_1" << std::endl;
116 return (ani_status)ANI_ERROR_CODE;
117 }
118
119 ani_namespace connection;
120 env->FindNamespace("L@ohos/net/connection/connection;", &connection);
121
122 std::array methods = {
123 ani_native_function{"getDefaultNetSync", nullptr, reinterpret_cast<void *>(getDefaultNetSync)},
124 };
125
126 if (ANI_OK != env->Namespace_BindNativeFunctions(connection, methods.data(), methods.size())) {
127 return (ani_status)ANI_ERROR_CODE;
128 };
129
130 *result = ANI_VERSION_1;
131 return ANI_OK;
132 }