diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000000000000000000000000000000000000..421498f7964fe0c3cfad75c1cac8040dbea5288e --- /dev/null +++ b/.clang-format @@ -0,0 +1,173 @@ +# Copyright (C) 2021-2022 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. + +Language: Cpp +# BasedOnStyle: LLVM +# 访问说明符(public、private等)的偏移 +AccessModifierOffset: -4 +# 开括号(开圆括号、开尖括号、开方括号)后的对齐 +AlignAfterOpenBracket: Align +# 连续赋值时,等号对齐 +AlignConsecutiveAssignments: false +# 连续赋值时,变量名对齐 +AlignConsecutiveDeclarations: false +# 左对齐逃脱换行(使用反斜杠换行)的反斜杠 +AlignEscapedNewlinesLeft: true +# 水平对齐二元和三元表达式的操作数 +AlignOperands: true +# 对齐连续的尾随的注释 +AlignTrailingComments: true +# 允许函数声明的所有参数在放在下一行 +AllowAllParametersOfDeclarationOnNextLine: false +# 允许短的块放在同一行 +AllowShortBlocksOnASingleLine: false +# 允许短的case标签放在同一行 +AllowShortCaseLabelsOnASingleLine: false +# 允许短的函数放在同一行: None, InlineOnly(定义在类中), Empty(空函数), Inline(定义在类中,空函数), All +AllowShortFunctionsOnASingleLine: Empty +# 允许短的if语句保持在同一行 +AllowShortIfStatementsOnASingleLine: false +# 允许短的循环保持在同一行 +AllowShortLoopsOnASingleLine: false +# 总是在定义返回类型后换行(deprecated) +AlwaysBreakAfterDefinitionReturnType: None +# 总是在返回类型后换行: None, All, TopLevel(顶级函数,不包括在类中的函数), +# AllDefinitions(所有的定义,不包括声明), TopLevelDefinitions(所有的顶级函数的定义) +AlwaysBreakAfterReturnType: None +# 总是在多行string字面量前换行 +AlwaysBreakBeforeMultilineStrings: true +# 总是在template声明后换行 +AlwaysBreakTemplateDeclarations: false +# false表示函数实参要么都在同一行,要么都各自一行 +BinPackArguments: true +# false表示所有形参要么都在同一行,要么都各自一行 +BinPackParameters: false +# 大括号换行,只有当BreakBeforeBraces设置为Custom时才有效 +BraceWrapping: + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: true + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false +# 在二元运算符前换行: None(在操作符后换行), NonAssignment(在非赋值的操作符前换行), All(在操作符前换行) +BreakBeforeBinaryOperators: None +# 在大括号前换行: Attach(始终将大括号附加到周围的上下文), Linux(除函数、命名空间和类定义,与Attach类似), +# Mozilla(除枚举、函数、记录定义,与Attach类似), Stroustrup(除函数定义、catch、else,与Attach类似), +# Allman(总是在大括号前换行), GNU(总是在大括号前换行,并对于控制语句的大括号增加额外的缩进), WebKit(在函数前换行), Custom +# 注:这里认为语句块也属于函数 +BreakBeforeBraces: Custom +# 在三元运算符前换行 +BreakBeforeTernaryOperators: true +# 在构造函数的初始化列表的逗号前换行 +BreakConstructorInitializersBeforeComma: false +# 每行字符的限制,0表示没有限制 +ColumnLimit: 120 +# 描述具有特殊意义的注释的正则表达式,它不应该被分割为多行或以其它方式改变 +CommentPragmas: "^ IWYU pragma:" +# 构造函数的初始化列表要么都在同一行,要么都各自一行 +ConstructorInitializerAllOnOneLineOrOnePerLine: true +# 构造函数的初始化列表的缩进宽度 +ConstructorInitializerIndentWidth: 4 +# 延续的行的缩进宽度 +ContinuationIndentWidth: 4 +# 去除C++11的列表初始化的大括号{后和}前的空格 +Cpp11BracedListStyle: true +# 继承最常用的指针和引用的对齐方式 +DerivePointerAlignment: false +# 关闭格式化 +DisableFormat: false +# 自动检测函数的调用和定义是否被格式为每行一个参数(Experimental) +ExperimentalAutoDetectBinPacking: false +# 需要被解读为foreach循环而不是函数调用的宏 +ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] +# 对#include进行排序,匹配了某正则表达式的#include拥有对应的优先级,匹配不到的则默认优先级为INT_MAX(优先级越小排序越靠前), +# 可以定义负数优先级从而保证某些#include永远在最前面 +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + - Regex: '^(<|"(gtest|isl|json)/)' + Priority: 3 + - Regex: ".*" + Priority: 1 +# 缩进case标签 +IndentCaseLabels: true +# 缩进宽度 +IndentWidth: 4 +# 函数返回类型换行时,缩进函数声明或函数定义的函数名 +IndentWrappedFunctionNames: true +# 保留在块开始处的空行 +KeepEmptyLinesAtTheStartOfBlocks: true +# 开始一个块的宏的正则表达式 +MacroBlockBegin: "" +# 结束一个块的宏的正则表达式 +MacroBlockEnd: "" +# 连续空行的最大数量 +MaxEmptyLinesToKeep: 1 +# 命名空间的缩进: None, Inner(缩进嵌套的命名空间中的内容), All +NamespaceIndentation: None +# 使用ObjC块时缩进宽度 +ObjCBlockIndentWidth: 4 +# 在ObjC的@property后添加一个空格 +ObjCSpaceAfterProperty: false +# 在ObjC的protocol列表前添加一个空格 +ObjCSpaceBeforeProtocolList: true +# 在call(后对函数调用换行的penalty +PenaltyBreakBeforeFirstCallParameter: 19 +# 在一个注释中引入换行的penalty +PenaltyBreakComment: 300 +# 第一次在<<前换行的penalty +PenaltyBreakFirstLessLess: 120 +# 在一个字符串字面量中引入换行的penalty +PenaltyBreakString: 1000 +# 对于每个在行字符数限制之外的字符的penalty +PenaltyExcessCharacter: 1000000 +# 将函数的返回类型放到它自己的行的penalty +PenaltyReturnTypeOnItsOwnLine: 60 +# 指针和引用的对齐: Left, Right, Middle +PointerAlignment: Right +# 允许重新排版注释 +ReflowComments: true +# 允许排序#include +SortIncludes: true +# 在C风格类型转换后添加空格 +SpaceAfterCStyleCast: false +# 在赋值运算符之前添加空格 +SpaceBeforeAssignmentOperators: true +# 开圆括号之前添加一个空格: Never, ControlStatements, Always +SpaceBeforeParens: ControlStatements +# 在空的圆括号中添加空格 +SpaceInEmptyParentheses: false +# 在尾随的评论前添加的空格数(只适用于//) +SpacesBeforeTrailingComments: 1 +# 在尖括号的<后和>前添加空格 +SpacesInAngles: false +# 在容器(ObjC和JavaScript的数组和字典等)字面量中添加空格 +SpacesInContainerLiterals: true +# 在C风格类型转换的括号中添加空格 +SpacesInCStyleCastParentheses: false +# 在圆括号的(后和)前添加空格 +SpacesInParentheses: false +# 在方括号的[后和]前添加空格,lamda表达式和未指明大小的数组的声明不受影响 +SpacesInSquareBrackets: false +# 标准: Cpp03, Cpp11, Auto +Standard: Cpp11 +# tab宽度 +TabWidth: 4 +# 使用tab字符: Never, ForIndentation, ForContinuationAndIndentation, Always +UseTab: Never \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..60a4b4bdb5f8c24093beb8e24a28a873d335bd22 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.idea +cmake-build-debug +*.patch \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..147cca212fa6323606e97cedc31926d349f0ffed --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,62 @@ +# Copyright (C) 2021-2022 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. + +cmake_minimum_required(VERSION 3.20) +project(CommunicationNetStack) + +set(CMAKE_CXX_STANDARD 23) + +include_directories( + ../../ace/napi/interfaces/kits + ../../ace/napi/native_engine/impl/quickjs + ../../ace/napi/ + ../../../third_party/node/src +) + +include_directories(utils/napi_utils/include) +include_directories(utils/common_utils/include) +include_directories(utils/event_manager/include) +include_directories(utils/base_context/include) +include_directories(utils/base_async_work/include) +include_directories(utils/module_template/include) + +include_directories(../../../utils/native/base/include/) + +include_directories(utils/log/include) +include_directories(../../../base/hiviewdfx/hilog/interfaces/native/innerkits/include) + +include_directories(test/napi/common) + +include_directories(../../../foundation/ace/ace_engine/frameworks/base/utils) + +include_directories(../../../third_party/quickjs) + +include_directories(../../../third_party/googletest/googletest/include) +include_directories(../../../third_party/libuv/include) + +link_directories(../../../utils/native/base/cmake-build-debug/src/securec) + +link_directories(../../../foundation/ace/napi/cmake-build-debug) + +link_directories(../../../third_party/quickjs) + +link_directories(../../../third_party/googletest/cmake-build-debug/googlemock/gtest) +link_directories(../../../third_party/googletest/cmake-build-debug/googlemock) +link_directories(../../../third_party/libuv/cmake-build-debug) + +link_directories(cmake-build-debug/utils) + +add_subdirectory(frameworks/js/builtin) +add_subdirectory(utils) +add_subdirectory(test/napi/http) +add_subdirectory(test/napi/socket) \ No newline at end of file diff --git a/frameworks/js/napi/BUILD.gn b/frameworks/js/napi/BUILD.gn index 58551988737aff7cb9e844c33e2d949da0001fb3..dd3ae5dd45005ffe37cd52f6988de316e66ab30d 100644 --- a/frameworks/js/napi/BUILD.gn +++ b/frameworks/js/napi/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2021 Huawei Device Co., Ltd. +# Copyright (c) 2021-2022 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 @@ -14,95 +14,142 @@ import("//build/ohos.gni") SUBSYSTEM_DIR = "//foundation/communication" -NETMANAGER_NAPI_ROOT = "$SUBSYSTEM_DIR/netstack/frameworks/js/napi/" +NETSTACK_NAPI_ROOT = "$SUBSYSTEM_DIR/netstack/frameworks/js/napi/" + +utils_source = [ + "$SUBSYSTEM_DIR/netstack/utils/base_context/src/netstack_base_context.cpp", + "$SUBSYSTEM_DIR/netstack/utils/common_utils/src/netstack_common_utils.cpp", + "$SUBSYSTEM_DIR/netstack/utils/event_manager/src/netstack_event_listener.cpp", + "$SUBSYSTEM_DIR/netstack/utils/event_manager/src/netstack_event_manager.cpp", + "$SUBSYSTEM_DIR/netstack/utils/module_template/src/netstack_module_template.cpp", + "$SUBSYSTEM_DIR/netstack/utils/napi_utils/src/netstack_napi_utils.cpp", +] + +utils_include = [ + "$SUBSYSTEM_DIR/netstack/utils/base_async_work/include", + "$SUBSYSTEM_DIR/netstack/utils/base_context/include", + "$SUBSYSTEM_DIR/netstack/utils/common_utils/include", + "$SUBSYSTEM_DIR/netstack/utils/event_manager/include", + "$SUBSYSTEM_DIR/netstack/utils/log/include", + "$SUBSYSTEM_DIR/netstack/utils/module_template/include", + "$SUBSYSTEM_DIR/netstack/utils/napi_utils/include", +] + +common_include = [ + "//foundation/ace/ace_engine/frameworks/base/utils", + "//foundation/ace/napi/interfaces/kits", + "//foundation/ace/napi", + "//third_party/node/src", +] + +common_deps = [ + "//foundation/ace/napi/:ace_napi", + "//utils/native/base:utils", +] + +common_external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", +] + +common_relative_install_dir = "module/net" +common_part_name = "netstack" +common_subsystem_name = "communication" ohos_shared_library("http") { include_dirs = [ - "//third_party/node/src", - "//foundation/ace/napi/interfaces/kits", - "$NETMANAGER_NAPI_ROOT/http/include", - "$SUBSYSTEM_DIR/netstack/utils/log/include", - "//third_party/curl/include" + "$NETSTACK_NAPI_ROOT/http/async_context/include", + "$NETSTACK_NAPI_ROOT/http/async_work/include", + "$NETSTACK_NAPI_ROOT/http/constant/include", + "$NETSTACK_NAPI_ROOT/http/http_exec/include", + "$NETSTACK_NAPI_ROOT/http/http_module/include", + "$NETSTACK_NAPI_ROOT/http/options/include", ] + include_dirs += utils_include + include_dirs += common_include + include_dirs += [ "//third_party/curl/include" ] sources = [ - "$NETMANAGER_NAPI_ROOT/http/src/http_napi.cpp", - "$NETMANAGER_NAPI_ROOT/http/src/http_request.cpp", - "$NETMANAGER_NAPI_ROOT/http/src/napi_util.cpp", + "http/async_context/src/request_context.cpp", + "http/async_work/src/http_async_work.cpp", + "http/constant/src/constant.cpp", + "http/http_exec/src/http_exec.cpp", + "http/http_module/src/http_module.cpp", + "http/options/src/http_request_options.cpp", + "http/options/src/http_response.cpp", ] + sources += utils_source - deps = [ - "//foundation/ace/napi/:ace_napi", - "//utils/native/base:utils", - "//third_party/curl:curl" - ] + deps = common_deps + deps += [ "//third_party/curl:curl" ] - external_deps = [ - "hiviewdfx_hilog_native:libhilog", - "ipc:ipc_core", - ] + defines = [ "NO_SSL_CERTIFICATION=1" ] + + external_deps = common_external_deps - relative_install_dir = "module/net" - part_name = "netstack" - subsystem_name = "communication" + relative_install_dir = common_relative_install_dir + part_name = common_part_name + subsystem_name = common_subsystem_name } ohos_shared_library("socket") { include_dirs = [ - "//third_party/node/src", - "//foundation/ace/napi/interfaces/kits", - "$NETMANAGER_NAPI_ROOT/http/include", - "$NETMANAGER_NAPI_ROOT/socket/include", - "$SUBSYSTEM_DIR/netstack/utils/log/include", - "//third_party" + "$NETSTACK_NAPI_ROOT/socket/async_context/include", + "$NETSTACK_NAPI_ROOT/socket/async_work/include", + "$NETSTACK_NAPI_ROOT/socket/constant/include", + "$NETSTACK_NAPI_ROOT/socket/socket_exec/include", + "$NETSTACK_NAPI_ROOT/socket/socket_module/include", + "$NETSTACK_NAPI_ROOT/socket/options/include", + "$NETSTACK_NAPI_ROOT/socket/task_queue/include", ] + include_dirs += utils_include + include_dirs += common_include sources = [ - "$NETMANAGER_NAPI_ROOT/http/src/napi_util.cpp", - "$NETMANAGER_NAPI_ROOT/socket/src/socket_napi.cpp", - "$NETMANAGER_NAPI_ROOT/socket/src/udp_socket.cpp", - "$NETMANAGER_NAPI_ROOT/socket/src/tcp_socket.cpp", + "socket/async_context/src/bind_context.cpp", + "socket/async_context/src/common_context.cpp", + "socket/async_context/src/connect_context.cpp", + "socket/async_context/src/tcp_extra_context.cpp", + "socket/async_context/src/tcp_send_context.cpp", + "socket/async_context/src/udp_extra_context.cpp", + "socket/async_context/src/udp_send_context.cpp", + "socket/async_work/src/socket_async_work.cpp", + "socket/options/src/extra_options_base.cpp", + "socket/options/src/net_address.cpp", + "socket/options/src/socket_remote_info.cpp", + "socket/options/src/socket_state_base.cpp", + "socket/options/src/tcp_connect_options.cpp", + "socket/options/src/tcp_extra_options.cpp", + "socket/options/src/tcp_send_options.cpp", + "socket/options/src/udp_extra_options.cpp", + "socket/options/src/udp_send_options.cpp", + "socket/socket_exec/src/socket_exec.cpp", + "socket/socket_module/src/socket_module.cpp", + "socket/task_queue/src/task_queue.cpp", ] + sources += utils_source - deps = [ - "//foundation/ace/napi/:ace_napi", - "//utils/native/base:utils" - ] + deps = common_deps - external_deps = [ - "hiviewdfx_hilog_native:libhilog", - "ipc:ipc_core", - ] + external_deps = common_external_deps - relative_install_dir = "module/net" - part_name = "netstack" - subsystem_name = "communication" + relative_install_dir = common_relative_install_dir + part_name = common_part_name + subsystem_name = common_subsystem_name } ohos_shared_library("websocket") { - include_dirs = [ - "//third_party/node/src", - "//foundation/ace/napi/interfaces/kits", - "$NETMANAGER_NAPI_ROOT/http/include", - "$NETMANAGER_NAPI_ROOT/websocket/include", - "$SUBSYSTEM_DIR/netstack/utils/log/include", - ] + include_dirs = [ "$NETSTACK_NAPI_ROOT/websocket/include" ] + include_dirs += utils_include + include_dirs += common_include - sources = [ - "$NETMANAGER_NAPI_ROOT/websocket/src/websocket_napi.cpp", - ] + sources = [ "$NETSTACK_NAPI_ROOT/websocket/src/websocket_napi.cpp" ] - deps = [ - "//foundation/ace/napi/:ace_napi", - "//utils/native/base:utils" - ] + deps = common_deps - external_deps = [ - "hiviewdfx_hilog_native:libhilog", - "ipc:ipc_core", - ] + external_deps = common_external_deps - relative_install_dir = "module/net" - part_name = "netstack" - subsystem_name = "communication" -} \ No newline at end of file + relative_install_dir = common_relative_install_dir + part_name = common_part_name + subsystem_name = common_subsystem_name +} diff --git a/frameworks/js/napi/http/async_context/include/request_context.h b/frameworks/js/napi/http/async_context/include/request_context.h new file mode 100644 index 0000000000000000000000000000000000000000..e6c33ff14e574ea8c8e173732611f28f6627165c --- /dev/null +++ b/frameworks/js/napi/http/async_context/include/request_context.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2021-2022 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_REQUEST_CONTEXT_H +#define COMMUNICATIONNETSTACK_REQUEST_CONTEXT_H + +#include "http_request_options.h" +#include "http_response.h" +#include "netstack_base_context.h" +#include "noncopyable.h" + +namespace OHOS::NetStack { + +class RequestContext final : public BaseContext { +public: + ACE_DISALLOW_COPY_AND_MOVE(RequestContext); + + RequestContext() = delete; + + explicit RequestContext(napi_env env, EventManager *manager); + + void ParseParams(napi_value *params, size_t paramsCount); + + HttpRequestOptions options; + + HttpResponse response; + +private: + bool CheckParamsType(napi_value *params, size_t paramsCount); + + void ParseNumberOptions(napi_value optionsValue); + + void ParseHeader(napi_value optionsValue); + + bool ParseExtraData(napi_value optionsValue); + + bool GetRequestBody(napi_value extraData); + + void UrlAndOptions(napi_value urlValue, napi_value optionsValue); +}; + +} // namespace OHOS::NetStack + +#endif /* COMMUNICATIONNETSTACK_REQUEST_CONTEXT_H */ diff --git a/frameworks/js/napi/http/async_context/src/request_context.cpp b/frameworks/js/napi/http/async_context/src/request_context.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4b178fa4e1ed1e2a4872bab7da37a5c23ddb1cd6 --- /dev/null +++ b/frameworks/js/napi/http/async_context/src/request_context.cpp @@ -0,0 +1,241 @@ +/* + * Copyright (C) 2021-2022 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 "request_context.h" + +#include "constant.h" +#include "http_exec.h" +#include "netstack_common_utils.h" +#include "netstack_log.h" +#include "netstack_napi_utils.h" +#include + +#define PARAM_JUST_URL 1 + +#define PARAM_URL_AND_OPTIONS_OR_CALLBACK 2 + +#define PARAM_URL_AND_OPTIONS_AND_CALLBACK 3 + +namespace OHOS::NetStack { + +RequestContext::RequestContext(napi_env env, EventManager *manager) : BaseContext(env, manager) {} + +void RequestContext::ParseParams(napi_value *params, size_t paramsCount) +{ + bool valid = CheckParamsType(params, paramsCount); + if (!valid) { + return; + } + + if (paramsCount == PARAM_JUST_URL) { + options.SetUrl(NapiUtils::GetStringFromValueUtf8(GetEnv(), params[0])); + SetParseOK(true); + return; + } + + if (paramsCount == PARAM_URL_AND_OPTIONS_OR_CALLBACK) { + napi_valuetype type = NapiUtils::GetValueType(GetEnv(), params[1]); + if (type == napi_function) { + options.SetUrl(NapiUtils::GetStringFromValueUtf8(GetEnv(), params[0])); + SetParseOK(SetCallback(params[1]) == napi_ok); + return; + } + if (type == napi_object) { + UrlAndOptions(params[0], params[1]); + return; + } + return; + } + + if (paramsCount == PARAM_URL_AND_OPTIONS_AND_CALLBACK) { + if (SetCallback(params[2]) != napi_ok) { + return; + } + UrlAndOptions(params[0], params[1]); + } +} + +bool RequestContext::CheckParamsType(napi_value *params, size_t paramsCount) +{ + if (paramsCount == PARAM_JUST_URL) { + // just url + return NapiUtils::GetValueType(GetEnv(), params[0]) == napi_string; + } + if (paramsCount == PARAM_URL_AND_OPTIONS_OR_CALLBACK) { + // should be url, callback or url, options + napi_valuetype type = NapiUtils::GetValueType(GetEnv(), params[1]); + return NapiUtils::GetValueType(GetEnv(), params[0]) == napi_string && + (type == napi_function || type == napi_object); + } + if (paramsCount == PARAM_URL_AND_OPTIONS_AND_CALLBACK) { + // should be url options and callback + return NapiUtils::GetValueType(GetEnv(), params[0]) == napi_string && + NapiUtils::GetValueType(GetEnv(), params[1]) == napi_object && + NapiUtils::GetValueType(GetEnv(), params[2]) == napi_function; + } + return false; +} + +void RequestContext::ParseNumberOptions(napi_value optionsValue) +{ + options.SetReadTimeout(NapiUtils::GetUint32Property(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_READ_TIMEOUT)); + if (options.GetReadTimeout() == 0) { + options.SetReadTimeout(HttpConstant::DEFAULT_READ_TIMEOUT); + } + + options.SetConnectTimeout( + NapiUtils::GetUint32Property(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_CONNECT_TIMEOUT)); + if (options.GetConnectTimeout() == 0) { + options.SetConnectTimeout(HttpConstant::DEFAULT_CONNECT_TIMEOUT); + } + + options.SetIfModifiedSince( + NapiUtils::GetUint32Property(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_IF_MODIFIED_SINCE)); + if (options.GetIfModifiedSince() == 0) { + options.SetIfModifiedSince(HttpConstant::DEFAULT_IF_MODIFIED_SINCE); + } + + options.SetFixedLengthStreamingMode( + NapiUtils::GetInt32Property(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_FIXED_LENGTH_STREAMING_MODE)); + if (options.GetFixedLengthStreamingMode() == 0) { + options.SetFixedLengthStreamingMode(HttpConstant::DEFAULT_FIXED_LENGTH_STREAMING_MODE); + } +} + +void RequestContext::ParseHeader(napi_value optionsValue) +{ + if (!NapiUtils::HasNamedProperty(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_HEADER)) { + return; + } + napi_value header = NapiUtils::GetNamedProperty(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_HEADER); + if (NapiUtils::GetValueType(GetEnv(), header) != napi_object) { + return; + } + auto names = NapiUtils::GetPropertyNames(GetEnv(), header); + std::for_each(names.begin(), names.end(), [header, this](const std::string &name) { + auto value = NapiUtils::GetStringPropertyUtf8(GetEnv(), header, name); + if (!value.empty()) { + options.SetHeader(CommonUtils::ToLower(name), value); + } + }); +} + +bool RequestContext::ParseExtraData(napi_value optionsValue) +{ + if (!NapiUtils::HasNamedProperty(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_EXTRA_DATA)) { + return HttpExec::MethodForGet(options.GetMethod()); + } + napi_value extraData = NapiUtils::GetNamedProperty(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_EXTRA_DATA); + + if (HttpExec::MethodForGet(options.GetMethod())) { + + std::string url = options.GetUrl(); + std::string param; + std::size_t index = url.find(HttpConstant::HTTP_URL_PARAM_START); + if (index != std::string::npos) { + param = url.substr(index + 1); + url = url.substr(0, index); + } + + napi_valuetype type = NapiUtils::GetValueType(GetEnv(), extraData); + + if (type == napi_string) { + std::string extraParam = NapiUtils::GetStringFromValueUtf8(GetEnv(), extraData); + + options.SetUrl(HttpExec::MakeUrl(url, param, extraParam)); + return true; + } + + if (type != napi_object) { + return false; + } + + std::string extraParam; + auto names = NapiUtils::GetPropertyNames(GetEnv(), extraData); + std::for_each(names.begin(), names.end(), [this, extraData, &extraParam](std::string name) { + auto value = NapiUtils::GetStringPropertyUtf8(GetEnv(), extraData, name); + NETSTACK_LOGI("url param name = %{public}s, value = %{public}s", name.c_str(), value.c_str()); + if (!name.empty() && !value.empty()) { + bool encodeName = HttpExec::EncodeUrlParam(name); + bool encodeValue = HttpExec::EncodeUrlParam(value); + if (encodeName || encodeValue) { + options.SetHeader(HttpConstant::HTTP_CONTENT_TYPE, HttpConstant::HTTP_CONTENT_TYPE_URL_ENCODE); + } + extraParam += + name + HttpConstant::HTTP_URL_NAME_VALUE_SEPARATOR + value + HttpConstant::HTTP_URL_PARAM_SEPARATOR; + } + }); + if (!extraParam.empty()) { + extraParam = extraParam.substr(0, extraParam.size() - 1); // remove the last & + } + + options.SetUrl(HttpExec::MakeUrl(url, param, extraParam)); + return true; + } + + if (HttpExec::MethodForPost(options.GetMethod())) { + return GetRequestBody(extraData); + } + return false; +} + +bool RequestContext::GetRequestBody(napi_value extraData) +{ + /* if body is empty, return false, or curl will wait for body */ + + napi_valuetype type = NapiUtils::GetValueType(GetEnv(), extraData); + + if (type == napi_string) { + auto body = NapiUtils::GetStringFromValueUtf8(GetEnv(), extraData); + if (body.empty()) { + return false; + } + options.SetBody(body.c_str(), body.size()); + return true; + } + + if (NapiUtils::ValueIsArrayBuffer(GetEnv(), extraData)) { + size_t length = 0; + void *data = NapiUtils::GetInfoFromArrayBufferValue(GetEnv(), extraData, &length); + if (data == nullptr) { + return false; + } + options.SetBody(data, length); + return true; + } + + NETSTACK_LOGE("Body do not support Object, because napi do not support json stringify for now"); + return false; +} + +void RequestContext::UrlAndOptions(napi_value urlValue, napi_value optionsValue) +{ + options.SetUrl(NapiUtils::GetStringFromValueUtf8(GetEnv(), urlValue)); + + std::string method = NapiUtils::GetStringPropertyUtf8(GetEnv(), optionsValue, HttpConstant::PARAM_KEY_METHOD); + if (method.empty()) { + method = HttpConstant::HTTP_METHOD_GET; + } + options.SetMethod(method); + + ParseHeader(optionsValue); + ParseNumberOptions(optionsValue); + + /* parse extra data here to recover header */ + + SetParseOK(ParseExtraData(optionsValue)); +} + +} // namespace OHOS::NetStack \ No newline at end of file diff --git a/frameworks/js/napi/socket/include/udp_send_options.h b/frameworks/js/napi/http/async_work/include/http_async_work.h similarity index 55% rename from frameworks/js/napi/socket/include/udp_send_options.h rename to frameworks/js/napi/http/async_work/include/http_async_work.h index f5e6379b3d7cca15161a41017818abbc329058f9..48b1fd5645838fa8a5a998573fa7caedc407aff1 100644 --- a/frameworks/js/napi/socket/include/udp_send_options.h +++ b/frameworks/js/napi/http/async_work/include/http_async_work.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Huawei Device Co., Ltd. + * Copyright (C) 2021-2022 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 @@ -13,32 +13,25 @@ * limitations under the License. */ -#ifndef UDP_SEND_OPTIONS_H -#define UDP_SEND_OPTIONS_H +#ifndef COMMUNICATIONNETSTACK_ASYNC_WORK_H +#define COMMUNICATIONNETSTACK_ASYNC_WORK_H #include "napi/native_api.h" #include "napi/native_node_api.h" -#include "napi_util.h" +#include "noncopyable.h" +#include "request_context.h" -namespace OHOS { -namespace NetManagerStandard { -class UDPSendOptions { +namespace OHOS::NetStack { + +class HttpAsyncWork final { public: - UDPSendOptions() {} - ~UDPSendOptions() {} - - std::string GetData() - { - return data_; - } - - void SetData(const std::string& data) - { - this->data_ = data; - } -private: - std::string data_ = ""; + ACE_DISALLOW_COPY_AND_MOVE(HttpAsyncWork); + + static void ExecRequest(napi_env env, void *data); + + static void RequestCallback(napi_env env, napi_status status, void *data); }; -} // namespace NetManagerStandard -} // namespace OHOS -#endif // UDP_SEND_OPTIONS_H \ No newline at end of file + +} // namespace OHOS::NetStack + +#endif /* COMMUNICATIONNETSTACK_ASYNC_WORK_H */ diff --git a/frameworks/js/napi/http/async_work/src/http_async_work.cpp b/frameworks/js/napi/http/async_work/src/http_async_work.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7125b9e5464e59347a77e7fb30c582b85b510c43 --- /dev/null +++ b/frameworks/js/napi/http/async_work/src/http_async_work.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2021-2022 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_async_work.h" + +#include "http_exec.h" +#include "netstack_base_async_work.h" +#include "netstack_napi_utils.h" +#include + +namespace OHOS::NetStack { + +void HttpAsyncWork::ExecRequest(napi_env env, void *data) +{ + BaseAsyncWork::ExecAsyncWork(env, data); +} + +void HttpAsyncWork::RequestCallback(napi_env env, napi_status status, void *data) +{ + BaseAsyncWork::AsyncWorkCallback(env, status, data); +} + +} // namespace OHOS::NetStack \ No newline at end of file diff --git a/frameworks/js/napi/http/constant/include/constant.h b/frameworks/js/napi/http/constant/include/constant.h new file mode 100644 index 0000000000000000000000000000000000000000..f5c83574a24bd7f8c4ef85ae45140a9e97044320 --- /dev/null +++ b/frameworks/js/napi/http/constant/include/constant.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2021-2022 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_CONSTANT_H +#define COMMUNICATIONNETSTACK_CONSTANT_H + +#include "noncopyable.h" +#include + +namespace OHOS::NetStack { + +class HttpConstant final { +public: + ACE_DISALLOW_COPY_AND_MOVE(HttpConstant); + + /* Http Method */ + static const char *const HTTP_METHOD_GET; + static const char *const HTTP_METHOD_HEAD; + static const char *const HTTP_METHOD_OPTIONS; + static const char *const HTTP_METHOD_TRACE; + static const char *const HTTP_METHOD_DELETE; + static const char *const HTTP_METHOD_POST; + static const char *const HTTP_METHOD_PUT; + static const char *const HTTP_METHOD_CONNECT; + + /* default options */ + static const uint32_t DEFAULT_READ_TIMEOUT; + static const uint32_t DEFAULT_CONNECT_TIMEOUT; + static const uint32_t DEFAULT_IF_MODIFIED_SINCE; + static const int32_t DEFAULT_FIXED_LENGTH_STREAMING_MODE; + + /* options key */ + static const char *const PARAM_KEY_METHOD; + static const char *const PARAM_KEY_EXTRA_DATA; + static const char *const PARAM_KEY_HEADER; + static const char *const PARAM_KEY_READ_TIMEOUT; + static const char *const PARAM_KEY_CONNECT_TIMEOUT; + static const char *const PARAM_KEY_IF_MODIFIED_SINCE; + static const char *const PARAM_KEY_FIXED_LENGTH_STREAMING_MODE; + + static const char *const RESPONSE_KEY_RESULT; + static const char *const RESPONSE_KEY_RESPONSE_CODE; + static const char *const RESPONSE_KEY_HEADER; + static const char *const RESPONSE_KEY_COOKIES; + + static const char *const HTTP_URL_PARAM_START; + static const char *const HTTP_URL_PARAM_SEPARATOR; + static const char *const HTTP_URL_NAME_VALUE_SEPARATOR; + static const char *const HTTP_HEADER_SEPARATOR; + static const char *const HTTP_LINE_SEPARATOR; + + static const char *const HTTP_DEFAULT_USER_AGENT; + static const char *const HTTP_DEFAULT_CA_PATH; + + static const char *const HTTP_CONTENT_TYPE; + static const char *const HTTP_CONTENT_TYPE_TEXT; + static const char *const HTTP_CONTENT_TYPE_URL_ENCODE; + static const char *const HTTP_CONTENT_TYPE_JSON; +}; + +} // namespace OHOS::NetStack + +#endif /* COMMUNICATIONNETSTACK_CONSTANT_H */ diff --git a/frameworks/js/napi/socket/include/udp_event_list.h b/frameworks/js/napi/http/constant/include/event_list.h similarity index 55% rename from frameworks/js/napi/socket/include/udp_event_list.h rename to frameworks/js/napi/http/constant/include/event_list.h index 905a9698d133f2789a584fd1ce1f3fb0d4d99d70..351f0d0e69312007d2954a793a2b8e76c051a8f6 100644 --- a/frameworks/js/napi/socket/include/udp_event_list.h +++ b/frameworks/js/napi/http/constant/include/event_list.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Huawei Device Co., Ltd. + * Copyright (C) 2021-2022 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 @@ -13,22 +13,9 @@ * limitations under the License. */ -#ifndef UDP_EVENT_LIST_H -#define UDP_EVENT_LIST_H +#ifndef COMMUNICATIONNETSTACK_EVENT_LIST_H +#define COMMUNICATIONNETSTACK_EVENT_LIST_H -#include "napi/native_api.h" -#include "napi/native_node_api.h" +#define ON_HEADER_RECEIVE "headerReceive" -namespace OHOS { -namespace NetManagerStandard { -class UDPSocket; -struct UdpEventListener { - napi_env env_; - int32_t eventType_; - bool isOnce_; - napi_ref callbackRef_; - UDPSocket *udpSocket_; -}; -} // namespace NetManagerStandard -} // namespace OHOS -#endif // UDP_EVENT_LIST_H \ No newline at end of file +#endif /* COMMUNICATIONNETSTACK_EVENT_LIST_H */ diff --git a/frameworks/js/napi/http/constant/src/constant.cpp b/frameworks/js/napi/http/constant/src/constant.cpp new file mode 100644 index 0000000000000000000000000000000000000000..475f9fa6b4b5a611015e7567b140f29395699a12 --- /dev/null +++ b/frameworks/js/napi/http/constant/src/constant.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2021-2022 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 "constant.h" + +namespace OHOS::NetStack { + +const char *const HttpConstant::HTTP_METHOD_GET = "GET"; +const char *const HttpConstant::HTTP_METHOD_HEAD = "HEAD"; +const char *const HttpConstant::HTTP_METHOD_OPTIONS = "OPTIONS"; +const char *const HttpConstant::HTTP_METHOD_TRACE = "TRACE"; +const char *const HttpConstant::HTTP_METHOD_DELETE = "DELETE"; +const char *const HttpConstant::HTTP_METHOD_POST = "POST"; +const char *const HttpConstant::HTTP_METHOD_PUT = "PUT"; +const char *const HttpConstant::HTTP_METHOD_CONNECT = "CONNECT"; + +const uint32_t HttpConstant::DEFAULT_READ_TIMEOUT = 60; +const uint32_t HttpConstant::DEFAULT_CONNECT_TIMEOUT = 60; +const uint32_t HttpConstant::DEFAULT_IF_MODIFIED_SINCE = 0; +const int32_t HttpConstant::DEFAULT_FIXED_LENGTH_STREAMING_MODE = -1; + +const char *const HttpConstant::PARAM_KEY_METHOD = "method"; +const char *const HttpConstant::PARAM_KEY_EXTRA_DATA = "extraData"; +const char *const HttpConstant::PARAM_KEY_HEADER = "header"; +const char *const HttpConstant::PARAM_KEY_READ_TIMEOUT = "readTimeout"; +const char *const HttpConstant::PARAM_KEY_CONNECT_TIMEOUT = "connectTimeout"; +const char *const HttpConstant::PARAM_KEY_IF_MODIFIED_SINCE = "ifModifiedSince"; +const char *const HttpConstant::PARAM_KEY_FIXED_LENGTH_STREAMING_MODE = "fixedLengthStreamingMode"; + +const char *const HttpConstant::RESPONSE_KEY_RESULT = "result"; +const char *const HttpConstant::RESPONSE_KEY_RESPONSE_CODE = "responseCode"; +const char *const HttpConstant::RESPONSE_KEY_HEADER = "header"; +const char *const HttpConstant::RESPONSE_KEY_COOKIES = "cookies"; + +const char *const HttpConstant::HTTP_URL_PARAM_START = "?"; +const char *const HttpConstant::HTTP_URL_PARAM_SEPARATOR = "&"; +const char *const HttpConstant::HTTP_URL_NAME_VALUE_SEPARATOR = "="; +const char *const HttpConstant::HTTP_HEADER_SEPARATOR = ":"; +const char *const HttpConstant::HTTP_LINE_SEPARATOR = "\r\n"; + +const char *const HttpConstant::HTTP_DEFAULT_USER_AGENT = "libcurl-agent/1.0"; +const char *const HttpConstant::HTTP_DEFAULT_CA_PATH = "/etc/ssl/certs"; + +const char *const HttpConstant::HTTP_CONTENT_TYPE = "content-type"; +const char *const HttpConstant::HTTP_CONTENT_TYPE_TEXT = "text/plain"; +const char *const HttpConstant::HTTP_CONTENT_TYPE_URL_ENCODE = "application/x-www-form-urlencoded"; +const char *const HttpConstant::HTTP_CONTENT_TYPE_JSON = "application/json"; + +} // namespace OHOS::NetStack \ No newline at end of file diff --git a/frameworks/js/napi/http/include/http_request.h b/frameworks/js/napi/http/http_exec/include/http_exec.h similarity index 31% rename from frameworks/js/napi/http/include/http_request.h rename to frameworks/js/napi/http/http_exec/include/http_exec.h index cc34d6bf2b0874467960b4a2ae0ef665e434d477..22695869c57ea4bfc6866c0d1a6d4eba445b4c8f 100644 --- a/frameworks/js/napi/http/include/http_request.h +++ b/frameworks/js/napi/http/http_exec/include/http_exec.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Huawei Device Co., Ltd. + * Copyright (C) 2021-2022 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 @@ -13,57 +13,61 @@ * limitations under the License. */ -#ifndef HTTP_REQUEST_H -#define HTTP_REQUEST_H +#ifndef COMMUNICATIONNETSTACK_HTTP_REQUEST_EXEC_H +#define COMMUNICATIONNETSTACK_HTTP_REQUEST_EXEC_H -#include +#include "curl/curl.h" +#include "napi/native_api.h" +#include "noncopyable.h" +#include "request_context.h" #include +#include -#include "base/security/deviceauth/deps_adapter/os_adapter/interfaces/linux/hc_log.h" -#include "http_request_options_context.h" -#include "netmgr_log_wrapper.h" +namespace OHOS::NetStack { -#include +class HttpExec final { +public: + ACE_DISALLOW_COPY_AND_MOVE(HttpExec); -namespace OHOS { -namespace NetManagerStandard { -constexpr int32_t URL_PREFIX_LENGTH = 8; + HttpExec() = default; -class HttpRequest { -public: - HttpRequest(); - ~HttpRequest(); + ~HttpExec() = default; + + static bool ExecRequest(RequestContext *context); + + static napi_value RequestCallback(RequestContext *context); + + static std::string MakeUrl(const std::string &url, std::string param, const std::string &extraParam); + + static bool MethodForGet(const std::string &method); + + static bool MethodForPost(const std::string &method); + + static bool EncodeUrlParam(std::string &str); + +private: + static bool Initialize(); + + static bool SetOption(CURL *curl, RequestContext *context, struct curl_slist *requestHeader); + + static size_t OnWritingMemoryBody(const void *data, size_t size, size_t memBytes, void *userData); + + static size_t OnWritingMemoryHeader(const void *data, size_t size, size_t memBytes, void *userData); + + static struct curl_slist *MakeHeaders(const std::vector &vec); - bool Initialize(); - void SetOptionURL(CURL *curl, HttpRequestOptionsContext *asyncContext); - bool GetCurlWriteData(HttpRequestOptionsContext *asyncContext); - void SetHeaders(std::string headersStr); - void SetHeader(CURL *curl); - void SetMethod(CURL *curl, HttpRequestOptionsContext *asyncContext); - bool SetOptionForPost(CURL *curl, HttpRequestOptionsContext *asyncContext); - bool SetOptionForGet(CURL *curl, HttpRequestOptionsContext *asyncContext); - void EmitHeader(HttpRequest *obj, const std::string &header); + static napi_value MakeResponseHeader(RequestContext *context); - bool NativeRequest(HttpRequestOptionsContext *asyncContext); + static void OnHeaderReceive(RequestContext *context, napi_value header); + + static bool IsUnReserved(unsigned char in); private: - static size_t OnWritingMemoryBody(const void *data, size_t size, size_t memBytes, void *userData) - { - ((std::string *)userData)->append((char *)data, 0, size * memBytes); - return size * memBytes; - } - - static size_t OnWritingMemoryHeader(const void *data, size_t size, size_t memBytes, void *userData) - { - ((std::string *)userData)->append((char *)data, 0, size * memBytes); - return size * memBytes; - } - - bool IsCaFile(const std::string &caFlie); - std::mutex mutex_; - bool initialized_ = false; - std::map headers_; + static std::mutex mutex_; + + static bool initialized_; }; -} // namespace NetManagerStandard -} // namespace OHOS -#endif // HTTP_REQUEST_H \ No newline at end of file + +} // namespace OHOS::NetStack + +#endif /* COMMUNICATIONNETSTACK_HTTP_REQUEST_EXEC_H */ diff --git a/frameworks/js/napi/http/http_exec/src/http_exec.cpp b/frameworks/js/napi/http/http_exec/src/http_exec.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c3fb367c8d7bfcb6c4b9b88049954a0698405e2f --- /dev/null +++ b/frameworks/js/napi/http/http_exec/src/http_exec.cpp @@ -0,0 +1,347 @@ +/* + * Copyright (C) 2021-2022 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_exec.h" + +#include "constant.h" +#include "event_list.h" +#include "netstack_common_utils.h" +#include "netstack_log.h" +#include "netstack_napi_utils.h" +#include "securec.h" +#include +#include +#include + +#define NETSTACK_CURL_EASY_SET_OPTION(handle, opt, data, asyncContext) \ + do { \ + CURLcode result = curl_easy_setopt(handle, opt, data); \ + if (result != CURLE_OK) { \ + const char *err = curl_easy_strerror(result); \ + NETSTACK_LOGE("Failed to set option: %{public}s, %{public}s %{public}d", #opt, err, result); \ + (asyncContext)->SetErrorCode(result); \ + return false; \ + } \ + } while (0) + +#define NETSTACK_CURL_EASY_PERFORM(handle, asyncContext) \ + do { \ + CURLcode result = curl_easy_perform(handle); \ + if (result != CURLE_OK) { \ + const char *err = curl_easy_strerror(result); \ + NETSTACK_LOGE("Failed to fetch, url:%{public}s, %{public}s %{public}d", \ + (asyncContext)->options.GetUrl().c_str(), err, result); \ + (asyncContext)->SetErrorCode(result); \ + return false; \ + } \ + } while (0) + +#define NETSTACK_CURL_EASY_GET_INFO(handle, opt, data, asyncContext) \ + do { \ + CURLcode result = curl_easy_getinfo(handle, opt, data); \ + if (result != CURLE_OK) { \ + const char *err = curl_easy_strerror(result); \ + NETSTACK_LOGE("Failed to get info: %{public}s, %{public}s %{public}d", #opt, err, result); \ + (asyncContext)->SetErrorCode(result); \ + return false; \ + } \ + } while (0) + +namespace OHOS::NetStack { + +std::mutex HttpExec::mutex_; + +bool HttpExec::initialized_ = false; + +bool HttpExec::ExecRequest(RequestContext *context) +{ + if (!Initialize()) { + return false; + } + + std::unique_ptr handle(curl_easy_init(), curl_easy_cleanup); + + if (!handle) { + NETSTACK_LOGE("Failed to create fetch task"); + return false; + } + + NETSTACK_LOGI("final url: %{public}s", context->options.GetUrl().c_str()); + + std::vector vec; + std::for_each(context->options.GetHeader().begin(), context->options.GetHeader().end(), + [&vec](const std::pair &p) { + vec.emplace_back(p.first + HttpConstant::HTTP_HEADER_SEPARATOR + p.second); + }); + std::unique_ptr header(MakeHeaders(vec), curl_slist_free_all); + + if (!SetOption(handle.get(), context, header.get())) { + NETSTACK_LOGE("set option failed"); + return false; + } + + NETSTACK_CURL_EASY_PERFORM(handle.get(), context); + + int32_t responseCode; + NETSTACK_CURL_EASY_GET_INFO(handle.get(), CURLINFO_RESPONSE_CODE, &responseCode, context); + + struct curl_slist *cookies = nullptr; + NETSTACK_CURL_EASY_GET_INFO(handle.get(), CURLINFO_COOKIELIST, &cookies, context); + std::unique_ptr cookiesHandle(cookies, curl_slist_free_all); + while (cookies) { + context->response.AppendCookies(cookies->data, strlen(cookies->data)); + if (cookies->next != nullptr) { + context->response.AppendCookies(HttpConstant::HTTP_LINE_SEPARATOR, + strlen(HttpConstant::HTTP_LINE_SEPARATOR)); + } + cookies = cookies->next; + } + + context->response.SetResponseCode(responseCode); + context->response.ParseHeaders(); + + return true; +} + +napi_value HttpExec::RequestCallback(RequestContext *context) +{ + napi_value object = NapiUtils::CreateObject(context->GetEnv()); + if (NapiUtils::GetValueType(context->GetEnv(), object) != napi_object) { + return nullptr; + } + + NapiUtils::SetUint32Property(context->GetEnv(), object, HttpConstant::RESPONSE_KEY_RESPONSE_CODE, + context->response.GetResponseCode()); + NapiUtils::SetStringPropertyUtf8(context->GetEnv(), object, HttpConstant::RESPONSE_KEY_COOKIES, + context->response.GetCookies()); + + napi_value header = MakeResponseHeader(context); + if (NapiUtils::GetValueType(context->GetEnv(), header) == napi_object) { + OnHeaderReceive(context, header); + NapiUtils::SetNamedProperty(context->GetEnv(), object, HttpConstant::RESPONSE_KEY_HEADER, header); + } + + auto contentType = CommonUtils::ToLower(const_cast &>( + context->response.GetHeader())[HttpConstant::HTTP_CONTENT_TYPE]); + if (contentType.find(HttpConstant::HTTP_CONTENT_TYPE_TEXT) != std::string::npos || + contentType.find(HttpConstant::HTTP_CONTENT_TYPE_JSON) != std::string::npos) { + /* now just support utf8 */ + NapiUtils::SetStringPropertyUtf8(context->GetEnv(), object, HttpConstant::RESPONSE_KEY_RESULT, + context->response.GetResult()); + return object; + } + + void *data = nullptr; + auto body = context->response.GetResult(); + napi_value arrayBuffer = NapiUtils::CreateArrayBuffer(context->GetEnv(), body.size(), &data); + if (data != nullptr && arrayBuffer != nullptr) { + (void)memcpy_s(data, body.size(), body.c_str(), body.size()); + NapiUtils::SetNamedProperty(context->GetEnv(), object, HttpConstant::RESPONSE_KEY_RESULT, arrayBuffer); + } + return object; +} + +std::string HttpExec::MakeUrl(const std::string &url, std::string param, const std::string &extraParam) +{ + if (param.empty()) { + param += extraParam; + } else { + param += HttpConstant::HTTP_URL_PARAM_SEPARATOR; + param += extraParam; + } + + if (param.empty()) { + return url; + } + + return url + HttpConstant::HTTP_URL_PARAM_START + param; +} + +bool HttpExec::MethodForGet(const std::string &method) +{ + return (method == HttpConstant::HTTP_METHOD_HEAD || method == HttpConstant::HTTP_METHOD_OPTIONS || + method == HttpConstant::HTTP_METHOD_DELETE || method == HttpConstant::HTTP_METHOD_TRACE || + method == HttpConstant::HTTP_METHOD_GET || method == HttpConstant::HTTP_METHOD_CONNECT); +} + +bool HttpExec::MethodForPost(const std::string &method) +{ + return (method == HttpConstant::HTTP_METHOD_POST || method == HttpConstant::HTTP_METHOD_PUT); +} + +bool HttpExec::EncodeUrlParam(std::string &str) +{ + char encoded[4]; + std::string encodeOut; + for (size_t i = 0; i < strlen(str.c_str()); ++i) { + auto c = static_cast(str.c_str()[i]); + if (IsUnReserved(c)) { + encodeOut += static_cast(c); + } else { + if (sprintf_s(encoded, sizeof(encoded), "%%%02X", c) < 0) { + return false; + } + encodeOut += encoded; + } + } + + if (str == encodeOut) { + return false; + } + str = encodeOut; + return true; +} + +bool HttpExec::Initialize() +{ + std::lock_guard lock(mutex_); + if (initialized_) { + return true; + } + NETSTACK_LOGI("call curl_global_init"); + if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { + NETSTACK_LOGE("Failed to initialize 'curl'"); + return false; + } + initialized_ = true; + return initialized_; +} + +bool HttpExec::SetOption(CURL *curl, RequestContext *context, struct curl_slist *requestHeader) +{ + const std::string &method = context->options.GetMethod(); + if (!MethodForGet(method) && !MethodForPost(method)) { + NETSTACK_LOGE("method %{public}s not supported", method.c_str()); + return false; + } + + NETSTACK_CURL_EASY_SET_OPTION(curl, CURLOPT_URL, context->options.GetUrl().c_str(), context); + NETSTACK_CURL_EASY_SET_OPTION(curl, CURLOPT_CUSTOMREQUEST, method.c_str(), context); + + NETSTACK_CURL_EASY_SET_OPTION(curl, CURLOPT_WRITEFUNCTION, OnWritingMemoryBody, context); + NETSTACK_CURL_EASY_SET_OPTION(curl, CURLOPT_WRITEDATA, context, context); + + NETSTACK_CURL_EASY_SET_OPTION(curl, CURLOPT_HEADERFUNCTION, OnWritingMemoryHeader, context); + NETSTACK_CURL_EASY_SET_OPTION(curl, CURLOPT_HEADERDATA, context, context); + + NETSTACK_CURL_EASY_SET_OPTION(curl, CURLOPT_HTTPHEADER, requestHeader, context); + + // Some servers don't like requests that are made without a user-agent field, so we provide one + NETSTACK_CURL_EASY_SET_OPTION(curl, CURLOPT_USERAGENT, HttpConstant::HTTP_DEFAULT_USER_AGENT, context); + + NETSTACK_CURL_EASY_SET_OPTION(curl, CURLOPT_FOLLOWLOCATION, 1L, context); + + /* first #undef CURL_DISABLE_COOKIES in curl config */ + NETSTACK_CURL_EASY_SET_OPTION(curl, CURLOPT_COOKIEFILE, "", context); + +#if NETSTACK_USE_PROXY + NETSTACK_CURL_EASY_SET_OPTION(curl, CURLOPT_PROXY, NETSTACK_PROXY_URL_PORT, context); + NETSTACK_CURL_EASY_SET_OPTION(curl, CURLOPT_PROXYTYPE, NETSTACK_PROXY_TYPE, context); + NETSTACK_CURL_EASY_SET_OPTION(curl, CURLOPT_HTTPPROXYTUNNEL, 1L, context); +#ifdef NETSTACK_PROXY_PASS + NETSTACK_CURL_EASY_SET_OPTION(curl, CURLOPT_PROXYUSERPWD, NETSTACK_PROXY_PASS, context); +#endif // NETSTACK_PROXY_PASS +#endif // NETSTACK_USE_PROXY + +#if NO_SSL_CERTIFICATION + // in real life, you should buy a ssl certification and rename it to /etc/ssl/cert.pem + NETSTACK_CURL_EASY_SET_OPTION(curl, CURLOPT_SSL_VERIFYHOST, 0L, context); + NETSTACK_CURL_EASY_SET_OPTION(curl, CURLOPT_SSL_VERIFYPEER, 0L, context); +#else + NETSTACK_CURL_EASY_SET_OPTION(curl, CURLOPT_CAPATH, HttpConstant::HTTP_DEFAULT_CA_PATH, context); +#endif // NO_SSL_CERTIFICATION + + NETSTACK_CURL_EASY_SET_OPTION(curl, CURLOPT_NOPROGRESS, 1L, context); + NETSTACK_CURL_EASY_SET_OPTION(curl, CURLOPT_NOSIGNAL, 1L, context); +#if HTTP_CURL_PRINT_VERBOSE + NETSTACK_CURL_EASY_SET_OPTION(curl, CURLOPT_VERBOSE, 1L, context); +#endif + NETSTACK_CURL_EASY_SET_OPTION(curl, CURLOPT_TIMEOUT, context->options.GetReadTimeout(), context); + NETSTACK_CURL_EASY_SET_OPTION(curl, CURLOPT_CONNECTTIMEOUT, context->options.GetConnectTimeout(), context); + + if (MethodForPost(method)) { + NETSTACK_CURL_EASY_SET_OPTION(curl, CURLOPT_POST, 1L, context); + if (!context->options.GetBody().empty()) { + NETSTACK_CURL_EASY_SET_OPTION(curl, CURLOPT_POSTFIELDS, context->options.GetBody().c_str(), context); + NETSTACK_CURL_EASY_SET_OPTION(curl, CURLOPT_POSTFIELDSIZE, context->options.GetBody().size(), context); + } + } + + return true; +} + +size_t HttpExec::OnWritingMemoryBody(const void *data, size_t size, size_t memBytes, void *userData) +{ + auto context = static_cast(userData); + context->response.AppendResult(data, size * memBytes); + return size * memBytes; +} + +size_t HttpExec::OnWritingMemoryHeader(const void *data, size_t size, size_t memBytes, void *userData) +{ + auto context = static_cast(userData); + context->response.AppendRawHeader(data, size * memBytes); + return size * memBytes; +} + +struct curl_slist *HttpExec::MakeHeaders(const std::vector &vec) +{ + struct curl_slist *header = nullptr; + std::for_each(vec.begin(), vec.end(), [&header](const std::string &s) { + if (!s.empty()) { + header = curl_slist_append(header, s.c_str()); + } + }); + return header; +} + +napi_value HttpExec::MakeResponseHeader(RequestContext *context) +{ + napi_value header = NapiUtils::CreateObject(context->GetEnv()); + if (NapiUtils::GetValueType(context->GetEnv(), header) == napi_object) { + std::for_each(context->response.GetHeader().begin(), context->response.GetHeader().end(), + [context, header](const std::pair &p) { + if (!p.first.empty() && !p.second.empty()) { + NapiUtils::SetStringPropertyUtf8(context->GetEnv(), header, p.first, p.second); + } + }); + } + return header; +} + +void HttpExec::OnHeaderReceive(RequestContext *context, napi_value header) +{ + napi_value undefined = NapiUtils::GetUndefined(context->GetEnv()); + context->Emit(ON_HEADER_RECEIVE, std::make_pair(undefined, header)); +} + +bool HttpExec::IsUnReserved(unsigned char in) +{ + if (('0' <= in && in <= '9') || ('a' <= in && in <= 'z') || ('A' <= in && in <= 'Z')) { + return true; + } + switch (in) { + case '-': + case '.': + case '_': + case '~': + return true; + default: + break; + } + return false; +} + +} // namespace OHOS::NetStack diff --git a/frameworks/js/napi/http/http_module/include/http_module.h b/frameworks/js/napi/http/http_module/include/http_module.h new file mode 100644 index 0000000000000000000000000000000000000000..6aae389a31deecccbef7e5e01636bace16bdf285 --- /dev/null +++ b/frameworks/js/napi/http/http_module/include/http_module.h @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2021-2022 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_MODULE_H +#define COMMUNICATIONNETSTACK_HTTP_MODULE_H + +#include "napi/native_api.h" + +namespace OHOS::NetStack { + +class HttpModuleExports { +public: + class HttpRequest { + public: + static constexpr const char *FUNCTION_REQUEST = "request"; + static constexpr const char *FUNCTION_DESTROY = "destroy"; + static constexpr const char *FUNCTION_ON = "on"; + static constexpr const char *FUNCTION_ONCE = "once"; + static constexpr const char *FUNCTION_OFF = "off"; + + static napi_value Request(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); + static napi_value Once(napi_env env, napi_callback_info info); + static napi_value Off(napi_env env, napi_callback_info info); + }; + + enum class ResponseCode { + OK = 200, + CREATED, + ACCEPTED, + NOT_AUTHORITATIVE, + NO_CONTENT, + RESET, + PARTIAL, + MULT_CHOICE = 300, + MOVED_PERM, + MOVED_TEMP, + SEE_OTHER, + NOT_MODIFIED, + USE_PROXY, + BAD_REQUEST = 400, + UNAUTHORIZED, + PAYMENT_REQUIRED, + FORBIDDEN, + NOT_FOUND, + BAD_METHOD, + NOT_ACCEPTABLE, + PROXY_AUTH, + CLIENT_TIMEOUT, + CONFLICT, + GONE, + LENGTH_REQUIRED, + PRECON_FAILED, + ENTITY_TOO_LARGE, + REQ_TOO_LONG, + UNSUPPORTED_TYPE, + INTERNAL_ERROR = 500, + NOT_IMPLEMENTED, + BAD_GATEWAY, + UNAVAILABLE, + GATEWAY_TIMEOUT, + VERSION, + }; + + static constexpr const char *FUNCTION_CREATE_HTTP = "createHttp"; + static constexpr const char *INTERFACE_REQUEST_METHOD = "RequestMethod"; + static constexpr const char *INTERFACE_RESPONSE_CODE = "ResponseCode"; + static constexpr const char *INTERFACE_HTTP_REQUEST = "HttpRequest"; + + static napi_value InitHttpModule(napi_env env, napi_value exports); + +private: + static napi_value CreateHttp(napi_env env, napi_callback_info info); + + static void DefineHttpRequestClass(napi_env env, napi_value exports); + + static void InitHttpProperties(napi_env env, napi_value exports); + + static void InitRequestMethod(napi_env env, napi_value exports); + + static void InitResponseCode(napi_env env, napi_value exports); +}; + +} // namespace OHOS::NetStack +#endif // COMMUNICATIONNETSTACK_HTTP_MODULE_H \ No newline at end of file diff --git a/frameworks/js/napi/http/http_module/src/http_module.cpp b/frameworks/js/napi/http/http_module/src/http_module.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f4ccda0efea0f9d164468e17ec710068bbc0b0a6 --- /dev/null +++ b/frameworks/js/napi/http/http_module/src/http_module.cpp @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2021-2022 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_module.h" + +#include "constant.h" +#include "event_list.h" +#include "http_async_work.h" +#include "netstack_log.h" +#include "netstack_module_template.h" + +#define DECLARE_RESPONSE_CODE(code) \ + DECLARE_NAPI_STATIC_PROPERTY(#code, NapiUtils::CreateUint32(env, static_cast(ResponseCode::code))) + +#define DECLARE_REQUEST_METHOD(method) \ + DECLARE_NAPI_STATIC_PROPERTY(HttpConstant::method, NapiUtils::CreateStringUtf8(env, HttpConstant::method)) + +#define REQUEST_ASYNC_WORK_NAME "ExecRequest" + +#define HTTP_MODULE_NAME "net.http" + +namespace OHOS::NetStack { + +napi_value HttpModuleExports::InitHttpModule(napi_env env, napi_value exports) +{ + DefineHttpRequestClass(env, exports); + InitHttpProperties(env, exports); + + return exports; +} + +napi_value HttpModuleExports::CreateHttp(napi_env env, napi_callback_info info) +{ + return ModuleTemplate::NewInstance(env, info, INTERFACE_HTTP_REQUEST, [](napi_env, void *data, void *) { + NETSTACK_LOGI("http request handle is finalized"); + auto manager = static_cast(data); + delete manager; + }); +} + +void HttpModuleExports::DefineHttpRequestClass(napi_env env, napi_value exports) +{ + std::initializer_list properties = { + DECLARE_NAPI_FUNCTION(HttpRequest::FUNCTION_REQUEST, HttpRequest::Request), + DECLARE_NAPI_FUNCTION(HttpRequest::FUNCTION_DESTROY, HttpRequest::Destroy), + DECLARE_NAPI_FUNCTION(HttpRequest::FUNCTION_ON, HttpRequest::On), + DECLARE_NAPI_FUNCTION(HttpRequest::FUNCTION_ONCE, HttpRequest::Once), + DECLARE_NAPI_FUNCTION(HttpRequest::FUNCTION_OFF, HttpRequest::Off), + }; + ModuleTemplate::DefineClass(env, exports, properties, INTERFACE_HTTP_REQUEST); +} + +void HttpModuleExports::InitHttpProperties(napi_env env, napi_value exports) +{ + std::initializer_list properties = { + DECLARE_NAPI_FUNCTION(FUNCTION_CREATE_HTTP, CreateHttp), + }; + NapiUtils::DefineProperties(env, exports, properties); + + InitRequestMethod(env, exports); + InitResponseCode(env, exports); +} + +void HttpModuleExports::InitRequestMethod(napi_env env, napi_value exports) +{ + std::initializer_list properties = { + DECLARE_REQUEST_METHOD(HTTP_METHOD_OPTIONS), DECLARE_REQUEST_METHOD(HTTP_METHOD_GET), + DECLARE_REQUEST_METHOD(HTTP_METHOD_HEAD), DECLARE_REQUEST_METHOD(HTTP_METHOD_POST), + DECLARE_REQUEST_METHOD(HTTP_METHOD_PUT), DECLARE_REQUEST_METHOD(HTTP_METHOD_DELETE), + DECLARE_REQUEST_METHOD(HTTP_METHOD_TRACE), DECLARE_REQUEST_METHOD(HTTP_METHOD_CONNECT), + }; + + napi_value requestMethod = NapiUtils::CreateObject(env); + NapiUtils::DefineProperties(env, requestMethod, properties); + + NapiUtils::SetNamedProperty(env, exports, INTERFACE_REQUEST_METHOD, requestMethod); +} + +void HttpModuleExports::InitResponseCode(napi_env env, napi_value exports) +{ + std::initializer_list properties = { + DECLARE_RESPONSE_CODE(OK), + DECLARE_RESPONSE_CODE(CREATED), + DECLARE_RESPONSE_CODE(ACCEPTED), + DECLARE_RESPONSE_CODE(NOT_AUTHORITATIVE), + DECLARE_RESPONSE_CODE(NO_CONTENT), + DECLARE_RESPONSE_CODE(RESET), + DECLARE_RESPONSE_CODE(PARTIAL), + DECLARE_RESPONSE_CODE(MULT_CHOICE), + DECLARE_RESPONSE_CODE(MOVED_PERM), + DECLARE_RESPONSE_CODE(MOVED_TEMP), + DECLARE_RESPONSE_CODE(SEE_OTHER), + DECLARE_RESPONSE_CODE(NOT_MODIFIED), + DECLARE_RESPONSE_CODE(USE_PROXY), + DECLARE_RESPONSE_CODE(BAD_REQUEST), + DECLARE_RESPONSE_CODE(UNAUTHORIZED), + DECLARE_RESPONSE_CODE(PAYMENT_REQUIRED), + DECLARE_RESPONSE_CODE(FORBIDDEN), + DECLARE_RESPONSE_CODE(NOT_FOUND), + DECLARE_RESPONSE_CODE(BAD_METHOD), + DECLARE_RESPONSE_CODE(NOT_ACCEPTABLE), + DECLARE_RESPONSE_CODE(PROXY_AUTH), + DECLARE_RESPONSE_CODE(CLIENT_TIMEOUT), + DECLARE_RESPONSE_CODE(CONFLICT), + DECLARE_RESPONSE_CODE(GONE), + DECLARE_RESPONSE_CODE(LENGTH_REQUIRED), + DECLARE_RESPONSE_CODE(PRECON_FAILED), + DECLARE_RESPONSE_CODE(ENTITY_TOO_LARGE), + DECLARE_RESPONSE_CODE(REQ_TOO_LONG), + DECLARE_RESPONSE_CODE(UNSUPPORTED_TYPE), + DECLARE_RESPONSE_CODE(INTERNAL_ERROR), + DECLARE_RESPONSE_CODE(NOT_IMPLEMENTED), + DECLARE_RESPONSE_CODE(BAD_GATEWAY), + DECLARE_RESPONSE_CODE(UNAVAILABLE), + DECLARE_RESPONSE_CODE(GATEWAY_TIMEOUT), + DECLARE_RESPONSE_CODE(VERSION), + }; + + napi_value responseCode = NapiUtils::CreateObject(env); + NapiUtils::DefineProperties(env, responseCode, properties); + + NapiUtils::SetNamedProperty(env, exports, INTERFACE_RESPONSE_CODE, responseCode); +} + +napi_value HttpModuleExports::HttpRequest::Request(napi_env env, napi_callback_info info) +{ + return ModuleTemplate::Interface(env, info, REQUEST_ASYNC_WORK_NAME, nullptr, + HttpAsyncWork::ExecRequest, HttpAsyncWork::RequestCallback); +} + +napi_value HttpModuleExports::HttpRequest::Destroy(napi_env env, napi_callback_info info) +{ + (void)env; + (void)info; + + return NapiUtils::GetUndefined(env); +} + +napi_value HttpModuleExports::HttpRequest::On(napi_env env, napi_callback_info info) +{ + return ModuleTemplate::On(env, info, {ON_HEADER_RECEIVE}, true); +} + +napi_value HttpModuleExports::HttpRequest::Once(napi_env env, napi_callback_info info) +{ + return ModuleTemplate::Once(env, info, {ON_HEADER_RECEIVE}, false); +} + +napi_value HttpModuleExports::HttpRequest::Off(napi_env env, napi_callback_info info) +{ + return ModuleTemplate::Off(env, info, {ON_HEADER_RECEIVE}); +} + +static napi_module g_httpModule = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = HttpModuleExports::InitHttpModule, + .nm_modname = HTTP_MODULE_NAME, + .nm_priv = nullptr, + .reserved = {nullptr}, +}; + +extern "C" __attribute__((constructor)) void RegisterHttpModule(void) +{ + napi_module_register(&g_httpModule); +} +} // namespace OHOS::NetStack diff --git a/frameworks/js/napi/http/include/http_enum_define.h b/frameworks/js/napi/http/include/http_enum_define.h deleted file mode 100644 index 1dbd4bc875edfa17e620b62282b25df1410e4b57..0000000000000000000000000000000000000000 --- a/frameworks/js/napi/http/include/http_enum_define.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2021 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 HTTP_ENUM_DEFINE_H -#define HTTP_ENUM_DEFINE_H - -namespace OHOS { -namespace NetManagerStandard { -enum class RequestMethod { OPTIONS = 0, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT }; - -enum ResponseCode { - OK = 200, - CREATED, - ACCEPTED, - NOT_AUTHORITATIVE, - NO_CONTENT, - RESET, - PARTIAL, - MULT_CHOICE = 300, - MOVED_PERM, - MOVED_TEMP, - SEE_OTHER, - NOT_MODIFIED, - USE_PROXY, - BAD_REQUEST = 400, - UNAUTHORIZED, - PAYMENT_REQUIRED, - FORBIDDEN, - NOT_FOUND, - BAD_METHOD, - NOT_ACCEPTABLE, - PROXY_AUTH, - CLIENT_TIMEOUT, - CONFLICT, - GONE, - LENGTH_REQUIRED, - PRECON_FAILED, - ENTITY_TOO_LARGE, - REQ_TOO_LONG, - UNSUPPORTED_TYPE, - INTERNAL_ERROR = 500, - NOT_IMPLEMENTED, - BAD_GATEWAY, - UNAVAILABLE, - GATEWAY_TIMEOUT, - VERSION -}; -} // namespace NetManagerStandard -} // namespace OHOS -#endif // HTTP_ENUM_DEFINE_H \ No newline at end of file diff --git a/frameworks/js/napi/http/include/http_napi.h b/frameworks/js/napi/http/include/http_napi.h deleted file mode 100644 index 5cbf4b03b794f27950658a6d66fd6b6e5ea5f6d8..0000000000000000000000000000000000000000 --- a/frameworks/js/napi/http/include/http_napi.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2021 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 HTTP_NAPI_H -#define HTTP_NAPI_H - -#include - -#include "http_event_list.h" -#include "http_request.h" -#include "napi_util.h" - -namespace OHOS { -namespace NetManagerStandard { -const int32_t MAX_URL_LENGTH = 1024; -constexpr int32_t URL_ARRAY_LENGTH = 256; -constexpr int32_t MAX_HTTP_OBJ_COUNT = 100; - -constexpr int32_t NONE_EVENT_TYPE = 0; -constexpr int32_t LISTEN_HTTP_WORK_STATE = 1; - -constexpr std::int32_t CREATE_MAX_PARA = 2; -constexpr std::int32_t SUBSCRIBE_MAX_PARA = 2; -constexpr std::int32_t UNSUBSCRIBE_MAX_PARA = 2; -constexpr std::int32_t PUBLISH_MAX_PARA_BY_PUBLISHDATA = 3; - -const std::string HEADER_RECEIVE = "headerReceive"; - -static std::mutex g_map_mutex_; - -static napi_value g_HttpRequestConstructorJS; -static std::map httpRequestInstances; -static std::list g_eventListenerList; - -napi_value CreateHttp(napi_env env, napi_callback_info info); -napi_value Request(napi_env env, napi_callback_info info); -napi_value Destroy(napi_env env, napi_callback_info info); -napi_value On(napi_env env, napi_callback_info info); -napi_value Off(napi_env env, napi_callback_info info); -napi_value HttpRequestConstructor(napi_env env, napi_callback_info info); -napi_value CreateHttp(napi_env env, napi_callback_info info); -} // namespace NetManagerStandard -} // namespace OHOS -#endif // HTTP_NAPI_H \ No newline at end of file diff --git a/frameworks/js/napi/http/include/http_request_options_context.h b/frameworks/js/napi/http/include/http_request_options_context.h deleted file mode 100644 index ef9c5f1e162e85a6631a06827a6033c65ee829e6..0000000000000000000000000000000000000000 --- a/frameworks/js/napi/http/include/http_request_options_context.h +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (C) 2021 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 HTTP_REQUEST_OPTIONS_CONTEXT_H -#define HTTP_REQUEST_OPTIONS_CONTEXT_H - -#include "http_base_context.h" -#include "http_enum_define.h" -#include "http_response.h" - -namespace OHOS { -namespace NetManagerStandard { -class HttpRequest; -class HttpRequestOptionsContext : public HttpBaseContext { -public: - HttpRequest *httpRequestInfo_; - -public: - HttpRequestOptionsContext() {} - ~HttpRequestOptionsContext() {} - - void SetRequestMethod(RequestMethod method) - { - this->method_ = method; - } - - RequestMethod GetRequestMethod() - { - return this->method_; - } - - void SetExtraData(const std::string &extraData) - { - this->extraData_ = extraData; - } - - std::string GetExtraData() - { - return this->extraData_; - } - - void SetHeader(const std::string &header) - { - this->header_ = header; - } - - std::string GetHeader() - { - return this->header_; - } - - void SetReadTimeout(const int32_t &readTimeout) - { - this->readTimeout_ = readTimeout; - } - - int32_t GetReadTimeout() - { - return this->readTimeout_; - } - - void SetConnectTimeout(const int32_t &connectTimeout) - { - this->connectTimeout_ = connectTimeout; - } - - int32_t GetConnectTimeout() - { - return this->connectTimeout_; - } - - void SetIfModifiedSince(const int32_t &ifModifiedSince) - { - this->ifModifiedSince_ = ifModifiedSince; - } - - int32_t GetIfModifiedSince() - { - return this->ifModifiedSince_; - } - - void SetUsingCache(const bool &usingCache) - { - this->usingCache_ = usingCache; - } - - bool GetUsingCache() - { - return this->usingCache_; - } - - void SetFixedLengthStreamingMode(const int32_t &fixedLengthStreamingMode) - { - this->fixedLengthStreamingMode_ = fixedLengthStreamingMode; - } - - int32_t GetFixedLengthStreamingMode() - { - return this->fixedLengthStreamingMode_; - } - - void SetUrl(const std::string &url) - { - this->url_ = url; - } - - std::string GetUrl() - { - return this->url_; - } - - void SetResponseData(HttpResponse &responseData) - { - this->responseData_ = responseData; - } - - HttpResponse GetResponseData() - { - return this->responseData_; - } - - void SetCaFile(const std::string &caFile) - { - this->cafile_ = caFile; - } - - std::string GetCaFile() - { - return this->cafile_; - } -private: - RequestMethod method_ = RequestMethod::GET; - std::string extraData_ = ""; - std::string header_ = ""; - int32_t readTimeout_ = 60; - int32_t connectTimeout_ = 60; - int32_t ifModifiedSince_ = 0; - bool usingCache_ = true; - int32_t fixedLengthStreamingMode_ = -1; - std::string url_ = ""; - HttpResponse responseData_; - std::string cafile_; -}; -} // namespace NetManagerStandard -} // namespace OHOS -#endif // HTTP_REQUEST_OPTIONS_CONTEXT_H \ No newline at end of file diff --git a/frameworks/js/napi/http/include/http_response.h b/frameworks/js/napi/http/include/http_response.h deleted file mode 100644 index 5d74363bed7a29324f888e9c7db725ae11992e29..0000000000000000000000000000000000000000 --- a/frameworks/js/napi/http/include/http_response.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2021 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 HTTP_RESPONSE_H -#define HTTP_RESPONSE_H - -#include "http_base_context.h" - -#include -#include - -namespace OHOS { -namespace NetManagerStandard { -class HttpResponse : public HttpBaseContext { -public: - HttpResponse() {} - ~HttpResponse() {} - - void SetResult(const std::string &result) - { - this->result_ = result; - } - - std::string GetResult() - { - return this->result_; - } - - void SetResponseCode(ResponseCode responseCode) - { - this->responseCode_ = responseCode; - } - - ResponseCode GetResponseCode() - { - return this->responseCode_; - } - - void SetHeader(const std::string &header) - { - this->header_ = header; - } - - std::string GetHeader() - { - return this->header_; - } - - void SetCookies(const std::vector &cookies) - { - this->cookies_ = cookies; - } - - std::vector GetCookies() - { - return this->cookies_; - } -private: - std::string result_ = ""; - enum ResponseCode responseCode_; - std::string header_ = ""; - std::vector cookies_; -}; -} // namespace NetManagerStandard -} // namespace OHOS -#endif // HTTP_RESPONSE_H \ No newline at end of file diff --git a/frameworks/js/napi/http/include/napi_util.h b/frameworks/js/napi/http/include/napi_util.h deleted file mode 100644 index 46291b5c11cf9fa67a37dae6dea60978ca7e5234..0000000000000000000000000000000000000000 --- a/frameworks/js/napi/http/include/napi_util.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2021 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 HTTP_NAPI_NAPI_UTIL_H -#define HTTP_NAPI_NAPI_UTIL_H - -#include -#include -#include -#include - -#include "napi/native_api.h" -#include "napi/native_node_api.h" - -namespace OHOS { -namespace NetManagerStandard { -using vecNapiType = std::vector; -constexpr int32_t MAX_CHAR_LENGTH = 64; -constexpr int32_t ERROR_DEFAULT = -1; -constexpr int32_t maxUrlLength = 1024; -constexpr int32_t SWITCH_PARAM_ZERO = 0; -constexpr int32_t SWITCH_PARAM_ONE = 1; -constexpr int32_t SWITCH_PARAM_TWO = 2; -constexpr int32_t SWITCH_PARAM_THREE = 3; - -class NapiUtil { -public: - static const int32_t MAX_TEXT_LENGTH = 4096; - static std::string ToUtf8(std::u16string str16); - static std::u16string ToUtf16(std::string str); - static napi_value CreateErrorMessage(napi_env env, std::string message, int32_t errorCode = ERROR_DEFAULT); - static napi_value CreateUndefined(napi_env env); - static bool MatchValueType(napi_env env, napi_value value, napi_valuetype targetType); - static bool MatchParameters( - napi_env env, const napi_value parameters[], std::initializer_list valueTypes); - static void SetPropertyInt32(napi_env env, napi_value object, std::string name, int32_t value); - static void SetPropertyStringUtf8(napi_env env, napi_value object, std::string name, std::string value); - static void SetPropertyBoolean(napi_env env, napi_value object, std::string name, bool value); - static napi_value ToInt32Value(napi_env env, int value); - static bool HasNamedProperty(napi_env env, napi_value object, std::string propertyName); - static bool HasNamedTypeProperty( - napi_env env, napi_value object, napi_valuetype type, std::string propertyName); - static bool MatchObjectProperty( - napi_env env, napi_value object, std::initializer_list> pairList); - static bool MatchOptionPropertyType( - napi_env env, napi_value object, napi_valuetype type, std::string propertyName); - static std::string GetStringFromValue(napi_env env, napi_value value); - static napi_value GetNamedProperty(napi_env env, napi_value object, std::string propertyName); - static bool MatchHttpRequestDataParameters(napi_env env, const napi_value parameters[], size_t parameterCount); - static bool MatchHttpOnDataParameters(napi_env env, const napi_value parameters[], size_t parameterCount); - static bool MatchHttpOffDataParameters(napi_env env, const napi_value parameters[], size_t parameterCount); - static void SetPropertyArray(napi_env env, napi_value object, std::string name, std::vector pdu); - static int32_t GetIntProperty(napi_env env, napi_value object, const std::string &propertyName); - static std::string GetStringProperty(napi_env env, napi_value object, const std::string &propertyName); -}; - -template -bool MatchParameters( - napi_env env, const napi_value argv[], size_t argc, std::tuple &theTuple, const vecNapiType &typeStd) -{ - bool typeMatched = false; - if (argc == typeStd.size()) { - vecNapiType paraType; - paraType.reserve(argc); - for (size_t i = 0; i < argc; i++) { - napi_valuetype valueType = napi_undefined; - napi_typeof(env, argv[i], &valueType); - paraType.emplace_back(valueType); - } - - if (paraType == typeStd) { - std::apply( - [env, argc, &argv](Ts &...tupleArgs) { - size_t index {0}; - ((index < argc ? NapiValueConverted(env, argv[index++], tupleArgs) : napi_ok), ...); - }, - theTuple); - typeMatched = true; - } - } - return typeMatched; -} -} // namespace NetManagerStandard -} // namespace OHOS -#endif // NAPI_UTIL_H \ No newline at end of file diff --git a/frameworks/js/napi/http/options/include/http_request_options.h b/frameworks/js/napi/http/options/include/http_request_options.h new file mode 100644 index 0000000000000000000000000000000000000000..f9cfa3a0e2d1bb9182effb89853a3e9ee2421d30 --- /dev/null +++ b/frameworks/js/napi/http/options/include/http_request_options.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2021-2022 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_REQUEST_OPTIONS_H +#define COMMUNICATIONNETSTACK_HTTP_REQUEST_OPTIONS_H + +#include +#include + +namespace OHOS::NetStack { +class HttpRequestOptions final { +public: + HttpRequestOptions(); + + void SetUrl(const std::string &url); + + void SetMethod(const std::string &method); + + void SetBody(const void *data, size_t length); + + void SetHeader(const std::string &key, const std::string &val); + + void SetReadTimeout(uint32_t readTimeout); + + void SetConnectTimeout(uint32_t connectTimeout); + + void SetIfModifiedSince(uint32_t ifModifiedSince); + + void SetFixedLengthStreamingMode(int32_t fixedLengthStreamingMode); + + [[nodiscard]] const std::string &GetUrl() const; + + [[nodiscard]] const std::string &GetMethod() const; + + [[nodiscard]] const std::string &GetBody() const; + + [[nodiscard]] const std::map &GetHeader() const; + + [[nodiscard]] uint32_t GetReadTimeout() const; + + [[nodiscard]] uint32_t GetConnectTimeout() const; + + [[nodiscard]] uint32_t GetIfModifiedSince() const; + + [[nodiscard]] int32_t GetFixedLengthStreamingMode() const; + +private: + std::string url_; + + std::string body_; + + std::string method_; + + std::map header_; + + uint32_t readTimeout_; + + uint32_t connectTimeout_; + + uint32_t ifModifiedSince_; + + int32_t fixedLengthStreamingMode_; +}; +} // namespace OHOS::NetStack + +#endif /* COMMUNICATIONNETSTACK_HTTP_REQUEST_OPTIONS_H */ diff --git a/frameworks/js/napi/http/options/include/http_response.h b/frameworks/js/napi/http/options/include/http_response.h new file mode 100644 index 0000000000000000000000000000000000000000..f4cac274edcd40b2ee91c7f363ac93359f816f81 --- /dev/null +++ b/frameworks/js/napi/http/options/include/http_response.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2021-2022 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_RESPONSE_H +#define COMMUNICATIONNETSTACK_HTTP_RESPONSE_H + +#include "napi/native_api.h" +#include +#include + +namespace OHOS::NetStack { + +class HttpResponse final { +public: + HttpResponse(); + + void AppendResult(const void *data, size_t length); + + void AppendRawHeader(const void *data, size_t length); + + void SetResponseCode(uint32_t responseCode); + + void ParseHeaders(); + + void AppendCookies(const void *data, size_t length); + + [[nodiscard]] const std::string &GetResult() const; + + [[nodiscard]] uint32_t GetResponseCode() const; + + [[nodiscard]] const std::map &GetHeader() const; + + [[nodiscard]] const std::string &GetCookies() const; + +private: + std::string result_; + + std::string rawHeader_; + + uint32_t responseCode_; + + std::map header_; + + std::string cookies_; +}; + +} // namespace OHOS::NetStack + +#endif /* COMMUNICATIONNETSTACK_HTTP_RESPONSE_H */ diff --git a/frameworks/js/napi/http/options/src/http_request_options.cpp b/frameworks/js/napi/http/options/src/http_request_options.cpp new file mode 100644 index 0000000000000000000000000000000000000000..789fb094f9fa49d540376b6c7813e72ebcd00ad5 --- /dev/null +++ b/frameworks/js/napi/http/options/src/http_request_options.cpp @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2021-2022 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_request_options.h" + +#include "constant.h" + +namespace OHOS::NetStack { + +HttpRequestOptions::HttpRequestOptions() + : method_(HttpConstant::HTTP_METHOD_GET), + readTimeout_(HttpConstant::DEFAULT_READ_TIMEOUT), + connectTimeout_(HttpConstant::DEFAULT_CONNECT_TIMEOUT), + ifModifiedSince_(HttpConstant::DEFAULT_IF_MODIFIED_SINCE), + fixedLengthStreamingMode_(HttpConstant::DEFAULT_FIXED_LENGTH_STREAMING_MODE) +{ + header_[HttpConstant::HTTP_CONTENT_TYPE] = HttpConstant::HTTP_CONTENT_TYPE_TEXT; // default +} + +void HttpRequestOptions::SetUrl(const std::string &url) +{ + url_ = url; +} + +void HttpRequestOptions::SetMethod(const std::string &method) +{ + method_ = method; +} + +void HttpRequestOptions::SetBody(const void *data, size_t length) +{ + body_.append(static_cast(data), length); +} + +void HttpRequestOptions::SetHeader(const std::string &key, const std::string &val) +{ + header_[key] = val; +} + +void HttpRequestOptions::SetReadTimeout(uint32_t readTimeout) +{ + readTimeout_ = readTimeout; +} + +void HttpRequestOptions::SetConnectTimeout(uint32_t connectTimeout) +{ + connectTimeout_ = connectTimeout; +} + +void HttpRequestOptions::SetIfModifiedSince(uint32_t ifModifiedSince) +{ + ifModifiedSince_ = ifModifiedSince; +} + +void HttpRequestOptions::SetFixedLengthStreamingMode(int32_t fixedLengthStreamingMode) +{ + fixedLengthStreamingMode_ = fixedLengthStreamingMode; +} + +const std::string &HttpRequestOptions::GetUrl() const +{ + return url_; +} + +const std::string &HttpRequestOptions::GetMethod() const +{ + return method_; +} + +const std::string &HttpRequestOptions::GetBody() const +{ + return body_; +} + +const std::map &HttpRequestOptions::GetHeader() const +{ + return header_; +} + +uint32_t HttpRequestOptions::GetReadTimeout() const +{ + return readTimeout_; +} + +uint32_t HttpRequestOptions::GetConnectTimeout() const +{ + return connectTimeout_; +} + +uint32_t HttpRequestOptions::GetIfModifiedSince() const +{ + return ifModifiedSince_; +} + +int32_t HttpRequestOptions::GetFixedLengthStreamingMode() const +{ + return fixedLengthStreamingMode_; +} + +} // namespace OHOS::NetStack \ No newline at end of file diff --git a/frameworks/js/napi/http/options/src/http_response.cpp b/frameworks/js/napi/http/options/src/http_response.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d2f046642f00047b1e2a3884623ef54d3392c2ff --- /dev/null +++ b/frameworks/js/napi/http/options/src/http_response.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2021-2022 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_response.h" + +#include "constant.h" +#include "netstack_common_utils.h" +#include + +namespace OHOS::NetStack { + +HttpResponse::HttpResponse() : responseCode_(0) {} + +void HttpResponse::AppendResult(const void *data, size_t length) +{ + result_.append(static_cast(data), length); +} + +void HttpResponse::AppendRawHeader(const void *data, size_t length) +{ + rawHeader_.append(static_cast(data), length); +} + +void HttpResponse::SetResponseCode(uint32_t responseCode) +{ + responseCode_ = responseCode; +} + +void HttpResponse::ParseHeaders() +{ + std::vector vec = CommonUtils::Split(rawHeader_, HttpConstant::HTTP_LINE_SEPARATOR); + for (const auto &header : vec) { + if (CommonUtils::Strip(header).empty()) { + continue; + } + size_t index = header.find(HttpConstant::HTTP_HEADER_SEPARATOR); + if (index == std::string::npos) { + header_[CommonUtils::Strip(header)] = ""; + continue; + } + header_[CommonUtils::ToLower(CommonUtils::Strip(header.substr(0, index)))] = + CommonUtils::Strip(header.substr(index + 1)); + } +} + +void HttpResponse::AppendCookies(const void *data, size_t length) +{ + cookies_.append(static_cast(data), length); +} + +const std::string &HttpResponse::GetResult() const +{ + return result_; +} + +uint32_t HttpResponse::GetResponseCode() const +{ + return responseCode_; +} + +const std::map &HttpResponse::GetHeader() const +{ + return header_; +} + +const std::string &HttpResponse::GetCookies() const +{ + return cookies_; +} + +} // namespace OHOS::NetStack \ No newline at end of file diff --git a/frameworks/js/napi/http/src/http_napi.cpp b/frameworks/js/napi/http/src/http_napi.cpp deleted file mode 100644 index 03c456909f4f5fe54807412a679ba411c9b8a42e..0000000000000000000000000000000000000000 --- a/frameworks/js/napi/http/src/http_napi.cpp +++ /dev/null @@ -1,632 +0,0 @@ -/* - * Copyright (C) 2021 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_napi.h" - -#include -#include -#include - -namespace OHOS { -namespace NetManagerStandard { -constexpr int32_t PARAMS_TWO_COUNT = 2; -constexpr int32_t PARAMS_THREE_COUNT = 3; -constexpr int32_t ARRAY_FIRST_INDEX = 1; -constexpr int32_t ARRAY_SECOND_INDEX = 2; -constexpr int32_t ARRAY_COUNT = 1; - -static int32_t FindMethodIndex(const std::string &key) -{ - std::vector methodVector = { - "OPTIONS ", "GET", "HEAD", "POST", "PUT", "DELETE", "TRACE", "CONNECT"}; - - int32_t result = -1; - std::vector::iterator it = find(methodVector.begin(), methodVector.end(), key); - if (it == methodVector.end()) { - NETMGR_LOGE("Get Method enum error"); - } else { - result = distance(methodVector.begin(), it); - } - return result; -} - -static void GetCaFilePathInfo(napi_env env, napi_value objValue, HttpRequestOptionsContext *asyncContext) -{ - std::string caFile = std::string("/etc/ssl/cacert.pem"); - bool result = NapiUtil::HasNamedTypeProperty(env, objValue, napi_string, "caFile"); - if (result) { - caFile = NapiUtil::GetStringProperty(env, objValue, "caFile"); - } - asyncContext->SetCaFile(caFile); -} - -static void GetRequestInfo(napi_env env, napi_value objValue, HttpRequestOptionsContext *asyncContext) -{ - RequestMethod method = RequestMethod::GET; - bool result = NapiUtil::HasNamedTypeProperty(env, objValue, napi_string, "method"); - if (result) { - method = static_cast(FindMethodIndex(NapiUtil::GetStringProperty(env, objValue, "method"))); - } - asyncContext->SetRequestMethod(method); - - std::string extraData = ""; - result = NapiUtil::HasNamedTypeProperty(env, objValue, napi_string, "extraData"); - if (result) { - extraData = NapiUtil::GetStringProperty(env, objValue, "extraData"); - } - asyncContext->SetExtraData(extraData); - - std::string header = std::string("'content-type': 'application/json'"); - result = NapiUtil::HasNamedTypeProperty(env, objValue, napi_string, "header"); - if (result) { - header = NapiUtil::GetStringProperty(env, objValue, "header"); - } - asyncContext->SetHeader(header); - - int32_t readTimeout = 60; - result = NapiUtil::HasNamedTypeProperty(env, objValue, napi_number, "readTimeout"); - if (result) { - readTimeout = NapiUtil::GetIntProperty(env, objValue, "readTimeout"); - } - asyncContext->SetReadTimeout(readTimeout); - - int32_t connectTimeout = 60; - result = NapiUtil::HasNamedTypeProperty(env, objValue, napi_number, "connectTimeout"); - if (result) { - connectTimeout = NapiUtil::GetIntProperty(env, objValue, "connectTimeout"); - } - asyncContext->SetConnectTimeout(connectTimeout); - - int32_t ifModifiedSince = 0; - result = NapiUtil::HasNamedTypeProperty(env, objValue, napi_number, "ifModifiedSince"); - if (result) { - ifModifiedSince = NapiUtil::GetIntProperty(env, objValue, "ifModifiedSince"); - } - asyncContext->SetIfModifiedSince(ifModifiedSince); - - bool usingCache = true; - result = NapiUtil::HasNamedTypeProperty(env, objValue, napi_number, "usingCache"); - if (result) { - usingCache = NapiUtil::GetIntProperty(env, objValue, "usingCache"); - } - asyncContext->SetUsingCache(usingCache); - - int32_t fixedLengthStreamingMode = -1; - result = NapiUtil::HasNamedTypeProperty(env, objValue, napi_number, "fixedLengthStreamingMode"); - if (result) { - fixedLengthStreamingMode = NapiUtil::GetIntProperty(env, objValue, "fixedLengthStreamingMode"); - } - asyncContext->SetFixedLengthStreamingMode(fixedLengthStreamingMode); - - GetCaFilePathInfo(env, objValue, asyncContext); -} - -/* - * native request - */ -static void NativeRequest(napi_env env, void *data) -{ - if (data == nullptr) { - NETMGR_LOGE("NativeRequest formal parameter data is null"); - return; - } - auto asyncContext = static_cast(data); - asyncContext->resolved_ = asyncContext->httpRequestInfo_->NativeRequest(asyncContext); -} - -/* - * request callback - */ -static void RequestCallback(napi_env env, napi_status status, void *data) -{ - if (data == nullptr) { - NETMGR_LOGE("RequestCallback data parameter address is nullptr"); - return; - } - auto asyncContext = static_cast(data); - napi_value callbackValue = nullptr; - - if (asyncContext->resolved_) { - /* - Assemble return values into object callbackValue - */ - napi_create_object(env, &callbackValue); - std::string result = asyncContext->GetResponseData().GetResult(); - ResponseCode responseCode = asyncContext->GetResponseData().GetResponseCode(); - std::string header = asyncContext->GetResponseData().GetHeader(); - std::vector cookie; - - NapiUtil::SetPropertyStringUtf8(env, callbackValue, "result", result); - NapiUtil::SetPropertyInt32(env, callbackValue, "responseCode", responseCode); - NapiUtil::SetPropertyStringUtf8(env, callbackValue, "header", header); - NapiUtil::SetPropertyArray(env, callbackValue, "cookie", cookie); - } else { - callbackValue = NapiUtil::CreateErrorMessage(env, "Request failed"); - } - if (asyncContext->callbackRef_ != nullptr) { - napi_value callbackFunc = nullptr; - napi_get_reference_value(env, asyncContext->callbackRef_, &callbackFunc); - napi_value callbackValues[] = {nullptr, nullptr}; - callbackValues[0] = asyncContext->resolved_ ? NapiUtil::CreateUndefined(env) : callbackValue; - callbackValues[1] = asyncContext->resolved_ ? callbackValue : NapiUtil::CreateUndefined(env); - napi_value undefined = nullptr; - napi_value callback = nullptr; - napi_value result = nullptr; - NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); - NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, asyncContext->callbackRef_, &callback)); - NAPI_CALL_RETURN_VOID( - env, napi_call_function(env, undefined, callback, std::size(callbackValues), callbackValues, &result)); - NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, asyncContext->callbackRef_)); - } else if (asyncContext->deferred_ != nullptr) { - if (asyncContext->resolved_) { - napi_resolve_deferred(env, asyncContext->deferred_, callbackValue); - } else { - napi_reject_deferred(env, asyncContext->deferred_, callbackValue); - } - } - napi_delete_async_work(env, asyncContext->work_); -} - -napi_value CreateHttp(napi_env env, napi_callback_info info) -{ - size_t argc = CREATE_MAX_PARA; - napi_value argv[CREATE_MAX_PARA]; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); - napi_value result = nullptr; - napi_value argvArray[] = {nullptr}; - napi_new_instance(env, g_HttpRequestConstructorJS, 0, argvArray, &result); - - return result; -} - -static napi_value GetRequestParams(napi_env env, size_t paraCount, napi_value *parameters, size_t paramNumber, - HttpRequestOptionsContext *asyncContext) -{ - char url[OHOS::NetManagerStandard::URL_ARRAY_LENGTH] = {0}; - size_t strLen = 0; - - NAPI_CALL(env, - napi_get_value_string_utf8( - env, parameters[0], url, OHOS::NetManagerStandard::URL_ARRAY_LENGTH - 1, &strLen)); - asyncContext->SetUrl(std::string(url, strLen)); - - if (paraCount == PARAMS_TWO_COUNT) { - if (NapiUtil::MatchValueType(env, parameters[ARRAY_FIRST_INDEX], napi_function)) { - NAPI_CALL(env, napi_create_reference(env, parameters[ARRAY_FIRST_INDEX], - ARRAY_COUNT, &(asyncContext->callbackRef_))); - } else if (NapiUtil::MatchValueType(env, parameters[ARRAY_FIRST_INDEX], napi_object)) { - GetRequestInfo(env, parameters[ARRAY_FIRST_INDEX], asyncContext); - } - } else if (paraCount == PARAMS_THREE_COUNT && - NapiUtil::MatchValueType(env, parameters[ARRAY_FIRST_INDEX], napi_object)) { - GetRequestInfo(env, parameters[ARRAY_SECOND_INDEX], asyncContext); - NAPI_CALL(env, napi_create_reference(env, parameters[ARRAY_SECOND_INDEX], ARRAY_COUNT, - &(asyncContext->callbackRef_))); - } - - return nullptr; -} - -/* - * http Request interface - */ -napi_value Request(napi_env env, napi_callback_info info) -{ - napi_value thisVar = nullptr; - size_t paraCount = 3; - napi_value parameters[3] = {nullptr, nullptr, nullptr}; - - NAPI_CALL(env, napi_get_cb_info(env, info, ¶Count, parameters, &thisVar, nullptr)); - NAPI_ASSERT(env, NapiUtil::MatchHttpRequestDataParameters(env, parameters, paraCount), "type mismatch"); - - HttpRequest *objectInfo = nullptr; - napi_valuetype valuetype; - - NAPI_CALL(env, napi_typeof(env, thisVar, &valuetype)); - NAPI_ASSERT(env, valuetype == napi_object, "Wrong argument type for arg0. Subscribe expected."); - napi_unwrap(env, thisVar, (void **)&objectInfo); - if (objectInfo == nullptr) { - NETMGR_LOGE("Http Request address is null"); - return nullptr; - } - - HttpRequestOptionsContext *asyncContext = nullptr; - auto requestKey = httpRequestInstances.find(objectInfo); - if (requestKey != httpRequestInstances.end()) { - asyncContext = requestKey->second; - } else { - NETMGR_LOGE("httpRequestInstances add HttpRequest pointer"); - return nullptr; - } - - GetRequestParams(env, paraCount, parameters, std::size(parameters), asyncContext); - - napi_value result = nullptr; - - if (asyncContext->callbackRef_ == nullptr) { - NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred_, &result)); - } else { - NAPI_CALL(env, napi_get_undefined(env, &result)); - } - napi_value resourceName = nullptr; - NAPI_CALL(env, napi_create_string_utf8(env, "Request", NAPI_AUTO_LENGTH, &resourceName)); - - NAPI_CALL(env, - napi_create_async_work(env, nullptr, resourceName, NativeRequest, RequestCallback, (void *)asyncContext, - &(asyncContext->work_))); - napi_status resultStatus = napi_queue_async_work(env, asyncContext->work_); - if (resultStatus == napi_ok) { - NETMGR_LOGI("Queue Async Work Successful"); - } - return result; -} - -/* - * http Destroy interface - */ -napi_value Destroy(napi_env env, napi_callback_info info) -{ - napi_value thisVar = nullptr; - size_t paraCount = 2; - napi_value parameters[2] = {nullptr, nullptr}; - - NAPI_CALL(env, napi_get_cb_info(env, info, ¶Count, parameters, &thisVar, nullptr)); - NAPI_ASSERT(env, NapiUtil::MatchHttpOnDataParameters(env, parameters, paraCount), "type mismatch"); - - HttpRequest *objectInfo = nullptr; - napi_valuetype valuetype; - - NAPI_CALL(env, napi_typeof(env, thisVar, &valuetype)); - NAPI_ASSERT(env, valuetype == napi_object, "Wrong argument type for arg0. Subscribe expected."); - napi_unwrap(env, thisVar, (void **)&objectInfo); - if (objectInfo == nullptr) { - NETMGR_LOGE("Destroy address is null"); - return nullptr; - } - - HttpRequestOptionsContext *asyncContext = nullptr; - auto requestKey = httpRequestInstances.find(objectInfo); - if (requestKey != httpRequestInstances.end()) { - asyncContext = requestKey->second; - } else { - NETMGR_LOGE("Destroy add HttpRequest pointer"); - return thisVar; - } - HttpRequest *httpRequest = requestKey->first; - httpRequestInstances.erase(requestKey); - g_eventListenerList.remove_if([objectInfo](EventListener listener)->bool { - napi_delete_reference(listener.env_, listener.callbackRef_); - return listener.httpRequestInfo_ == objectInfo; - }); - - delete asyncContext; - delete httpRequest; - - return thisVar; -} - -bool MatchEventType(const std::string &type, const std::string &goalTypeStr) -{ - return goalTypeStr.compare(type) == 0; -} - -int32_t GetEventType(const std::string &type) -{ - if (MatchEventType(type, HEADER_RECEIVE)) { - return LISTEN_HTTP_WORK_STATE; - } - return NONE_EVENT_TYPE; -} - -/* - * http On interface - */ -napi_value On(napi_env env, napi_callback_info info) -{ - napi_value thisVar = nullptr; - size_t paraCount = 2; - napi_value parameters[2] = {nullptr, nullptr}; - - NAPI_CALL(env, napi_get_cb_info(env, info, ¶Count, parameters, &thisVar, nullptr)); - NAPI_ASSERT(env, NapiUtil::MatchHttpOnDataParameters(env, parameters, paraCount), "type mismatch"); - - HttpRequest *objectInfo = nullptr; - napi_valuetype valuetype; - NAPI_CALL(env, napi_typeof(env, thisVar, &valuetype)); - NAPI_ASSERT(env, valuetype == napi_object, "Wrong argument type for arg0. Subscribe expected."); - napi_unwrap(env, thisVar, (void **)&objectInfo); - if (objectInfo == nullptr) { - NETMGR_LOGE("On address is null"); - return nullptr; - } - - HttpRequestOptionsContext *asyncContext = nullptr; - auto requestKey = httpRequestInstances.find(objectInfo); - if (requestKey != httpRequestInstances.end()) { - asyncContext = requestKey->second; - } else { - NETMGR_LOGE("On add HttpRequest pointer"); - return thisVar; - } - - char eventTypeChars[OHOS::NetManagerStandard::URL_ARRAY_LENGTH] = {0}; - size_t strLen = 0; - - NAPI_CALL(env, - napi_get_value_string_utf8( - env, parameters[0], eventTypeChars, OHOS::NetManagerStandard::URL_ARRAY_LENGTH - 1, &strLen)); - - napi_ref callbackRef = nullptr; - - if (paraCount == PARAMS_TWO_COUNT) { - napi_create_reference(env, parameters[ARRAY_FIRST_INDEX], ARRAY_COUNT, &callbackRef); - } - napi_value result = nullptr; - uint32_t eventType = GetEventType(eventTypeChars); - struct EventListener listener = {env, eventType, true, callbackRef, objectInfo}; - if (eventType != NONE_EVENT_TYPE) { - g_eventListenerList.push_back(listener); - result = thisVar; - } - - return thisVar; -} - -/* - * http Off interface - */ -napi_value Off(napi_env env, napi_callback_info info) -{ - napi_value thisVar = nullptr; - size_t paraCount = 2; - napi_value parameters[2] = {nullptr, nullptr}; - - NAPI_CALL(env, napi_get_cb_info(env, info, ¶Count, parameters, &thisVar, nullptr)); - NAPI_ASSERT(env, NapiUtil::MatchHttpOnDataParameters(env, parameters, paraCount), "type mismatch"); - - HttpRequest *objectInfo = nullptr; - napi_valuetype valuetype; - NAPI_CALL(env, napi_typeof(env, thisVar, &valuetype)); - NAPI_ASSERT(env, valuetype == napi_object, "Wrong argument type for arg0. Subscribe expected."); - napi_unwrap(env, thisVar, (void **)&objectInfo); - if (objectInfo == nullptr) { - NETMGR_LOGE("Off address is null"); - return nullptr; - } - - HttpRequestOptionsContext *asyncContext = nullptr; - auto requestKey = httpRequestInstances.find(objectInfo); - if (requestKey != httpRequestInstances.end()) { - asyncContext = requestKey->second; - } else { - NETMGR_LOGE("Off add HttpRequest pointer"); - return thisVar; - } - - char eventTypeChars[OHOS::NetManagerStandard::URL_ARRAY_LENGTH] = {0}; - size_t strLen = 0; - - NAPI_CALL(env, - napi_get_value_string_utf8( - env, parameters[0], eventTypeChars, OHOS::NetManagerStandard::URL_ARRAY_LENGTH - 1, &strLen)); - - napi_ref callbackRef = nullptr; - if (paraCount == PARAMS_TWO_COUNT) { - napi_create_reference(env, parameters[ARRAY_FIRST_INDEX], ARRAY_COUNT, &callbackRef); - } - napi_value result = nullptr; - uint32_t eventType = GetEventType(eventTypeChars); - struct EventListener listener = {env, eventType, true, callbackRef, objectInfo}; - if (eventType != NONE_EVENT_TYPE) { - napi_delete_reference(env, listener.callbackRef_); - g_eventListenerList.remove_if([objectInfo](EventListener listener)->bool { - return listener.httpRequestInfo_ == objectInfo; - }); - result = thisVar; - } - - return thisVar; -} - -napi_value HttpRequestConstructor(napi_env env, napi_callback_info info) -{ - size_t argc = 1; - napi_value argv[1]; - napi_value thisVar = nullptr; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr)); - auto objectInfo = new HttpRequest(); - auto asyncContext = new HttpRequestOptionsContext(); - if (httpRequestInstances.size() <= MAX_HTTP_OBJ_COUNT) { - asyncContext->httpRequestInfo_ = objectInfo; - httpRequestInstances[objectInfo] = asyncContext; - } else { - NETMGR_LOGE("HTTP object count max 100"); - return thisVar; - } - - napi_wrap(env, thisVar, objectInfo, - [](napi_env env, void *data, void *hint) { - HttpRequest *objectInfo = (HttpRequest *)data; - if (objectInfo) { - delete objectInfo; - objectInfo = nullptr; - } - }, - nullptr, nullptr); - - return thisVar; -} - -EXTERN_C_START -napi_value HttpFunctionInit(napi_env env, napi_value exports) -{ - napi_property_descriptor properties[] = { - DECLARE_NAPI_FUNCTION("request", Request), - DECLARE_NAPI_FUNCTION("destroy", Destroy), - DECLARE_NAPI_FUNCTION("on", On), - DECLARE_NAPI_FUNCTION("off", Off), - }; - NAPI_CALL(env, - napi_define_class(env, "HttpRequest", NAPI_AUTO_LENGTH, HttpRequestConstructor, nullptr, - sizeof(properties) / sizeof(*properties), properties, &g_HttpRequestConstructorJS)); - - return exports; -} - -napi_value HttpPropertyInit(napi_env env, napi_value exports) -{ - napi_value ok = nullptr; - napi_value created = nullptr; - napi_value accepted = nullptr; - napi_value not_authoritative = nullptr; - napi_value no_content = nullptr; - napi_value reset = nullptr; - napi_value partial = nullptr; - napi_value mult_choice = nullptr; - napi_value moved_perm = nullptr; - napi_value moved_temp = nullptr; - napi_value see_other = nullptr; - napi_value not_modified = nullptr; - napi_value use_proxy = nullptr; - napi_value bad_request = nullptr; - napi_value unauthorized = nullptr; - napi_value payment_required = nullptr; - napi_value forbidden = nullptr; - napi_value not_found = nullptr; - napi_value bad_method = nullptr; - napi_value not_acceptable = nullptr; - napi_value proxy_auth = nullptr; - napi_value client_timeou = nullptr; - napi_value conflict = nullptr; - napi_value gone = nullptr; - napi_value length_required = nullptr; - napi_value precon_failed = nullptr; - napi_value entity_too_large = nullptr; - napi_value req_too_long = nullptr; - napi_value unsupported = nullptr; - napi_value internal = nullptr; - napi_value not_implemented = nullptr; - napi_value bad_gateway = nullptr; - napi_value unavailable = nullptr; - napi_value gateway_timeout = nullptr; - napi_value version = nullptr; - - napi_create_int32(env, OK, &ok); - napi_create_int32(env, CREATED, &created); - napi_create_int32(env, ACCEPTED, &accepted); - napi_create_int32(env, NOT_AUTHORITATIVE, ¬_authoritative); - napi_create_int32(env, NO_CONTENT, &no_content); - napi_create_int32(env, RESET, &reset); - napi_create_int32(env, PARTIAL, &partial); - napi_create_int32(env, MULT_CHOICE, &mult_choice); - napi_create_int32(env, MOVED_PERM, &moved_perm); - napi_create_int32(env, MOVED_TEMP, &moved_temp); - napi_create_int32(env, SEE_OTHER, &see_other); - napi_create_int32(env, NOT_MODIFIED, ¬_modified); - napi_create_int32(env, USE_PROXY, &use_proxy); - napi_create_int32(env, BAD_REQUEST, &bad_request); - napi_create_int32(env, UNAUTHORIZED, &unauthorized); - napi_create_int32(env, PAYMENT_REQUIRED, &payment_required); - napi_create_int32(env, FORBIDDEN, &forbidden); - napi_create_int32(env, NOT_FOUND, ¬_found); - napi_create_int32(env, BAD_METHOD, &bad_method); - napi_create_int32(env, NOT_ACCEPTABLE, ¬_acceptable); - napi_create_int32(env, PROXY_AUTH, &proxy_auth); - napi_create_int32(env, CLIENT_TIMEOUT, &client_timeou); - napi_create_int32(env, CONFLICT, &conflict); - napi_create_int32(env, GONE, &gone); - napi_create_int32(env, LENGTH_REQUIRED, &length_required); - napi_create_int32(env, PRECON_FAILED, &precon_failed); - napi_create_int32(env, ENTITY_TOO_LARGE, &entity_too_large); - napi_create_int32(env, REQ_TOO_LONG, &req_too_long); - napi_create_int32(env, UNSUPPORTED_TYPE, &unsupported); - napi_create_int32(env, INTERNAL_ERROR, &internal); - napi_create_int32(env, NOT_IMPLEMENTED, ¬_implemented); - napi_create_int32(env, BAD_GATEWAY, &bad_gateway); - napi_create_int32(env, UNAVAILABLE, &unavailable); - napi_create_int32(env, GATEWAY_TIMEOUT, &gateway_timeout); - napi_create_int32(env, VERSION, &version); - - napi_property_descriptor desc[] = {DECLARE_NAPI_FUNCTION("createHttp", CreateHttp), - DECLARE_NAPI_STATIC_PROPERTY("OK", ok), DECLARE_NAPI_STATIC_PROPERTY("CREATED", created), - DECLARE_NAPI_STATIC_PROPERTY("ACCEPTED", accepted), - DECLARE_NAPI_STATIC_PROPERTY("NOT_AUTHORITATIVE", not_authoritative), - DECLARE_NAPI_STATIC_PROPERTY("NO_CONTENT", no_content), DECLARE_NAPI_STATIC_PROPERTY("RESET", reset), - DECLARE_NAPI_STATIC_PROPERTY("PARTIAL", partial), DECLARE_NAPI_STATIC_PROPERTY("MULT_CHOICE", mult_choice), - DECLARE_NAPI_STATIC_PROPERTY("MOVED_PERM", moved_perm), - DECLARE_NAPI_STATIC_PROPERTY("MOVED_TEMP", moved_temp), - DECLARE_NAPI_STATIC_PROPERTY("SEE_OTHER", see_other), - DECLARE_NAPI_STATIC_PROPERTY("NOT_MODIFIED", not_modified), - DECLARE_NAPI_STATIC_PROPERTY("USE_PROXY", use_proxy), - DECLARE_NAPI_STATIC_PROPERTY("BAD_REQUEST", bad_request), - DECLARE_NAPI_STATIC_PROPERTY("UNAUTHORIZED", unauthorized), - DECLARE_NAPI_STATIC_PROPERTY("PAYMENT_REQUIRED", payment_required), - DECLARE_NAPI_STATIC_PROPERTY("FORBIDDEN", forbidden), DECLARE_NAPI_STATIC_PROPERTY("NOT_FOUND", not_found), - DECLARE_NAPI_STATIC_PROPERTY("BAD_METHOD", bad_method), - DECLARE_NAPI_STATIC_PROPERTY("NOT_ACCEPTABLE", not_acceptable), - DECLARE_NAPI_STATIC_PROPERTY("PROXY_AUTH", proxy_auth), - DECLARE_NAPI_STATIC_PROPERTY("CLIENT_TIMEOUT", client_timeou), - DECLARE_NAPI_STATIC_PROPERTY("CONFLICT", conflict), DECLARE_NAPI_STATIC_PROPERTY("GONE", gone), - DECLARE_NAPI_STATIC_PROPERTY("LENGTH_REQUIRED", length_required), - DECLARE_NAPI_STATIC_PROPERTY("PRECON_FAILED", precon_failed), - DECLARE_NAPI_STATIC_PROPERTY("ENTITY_TOO_LARGE", entity_too_large), - DECLARE_NAPI_STATIC_PROPERTY("REQ_TOO_LONG", req_too_long), - DECLARE_NAPI_STATIC_PROPERTY("UNSUPPORTED_TYPE", unsupported), - DECLARE_NAPI_STATIC_PROPERTY("INTERNAL_ERROR", internal), - DECLARE_NAPI_STATIC_PROPERTY("NOT_IMPLEMENTED", not_implemented), - DECLARE_NAPI_STATIC_PROPERTY("BAD_GATEWAY", bad_gateway), - DECLARE_NAPI_STATIC_PROPERTY("UNAVAILABLE", unavailable), - DECLARE_NAPI_STATIC_PROPERTY("GATEWAY_TIMEOUT", gateway_timeout), - DECLARE_NAPI_STATIC_PROPERTY("VERSION", version)}; - - NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc)); - - return exports; -} - -/* - * Module export function - */ -static napi_value Init(napi_env env, napi_value exports) -{ - /* - * Propertise define - */ - HttpFunctionInit(env, exports); - HttpPropertyInit(env, exports); - - return exports; -} -EXTERN_C_END - -/* - * Module define - */ -static napi_module g_httpModule = { - .nm_version = 1, - .nm_flags = 0, - .nm_filename = nullptr, - .nm_register_func = Init, - .nm_modname = "net.http", - .nm_priv = ((void *)0), - .reserved = {(void *)0}, -}; - -extern "C" __attribute__((constructor)) void RegisterHttpModule(void) -{ - napi_module_register(&g_httpModule); -} -} // namespace NetManagerStandard -} // namespace OHOS diff --git a/frameworks/js/napi/http/src/http_request.cpp b/frameworks/js/napi/http/src/http_request.cpp deleted file mode 100644 index a551e328d9acd3c80c5dbc374662a83477b9de24..0000000000000000000000000000000000000000 --- a/frameworks/js/napi/http/src/http_request.cpp +++ /dev/null @@ -1,326 +0,0 @@ -/* - * Copyright (C) 2021 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_request.h" -#include "http_event_list.h" -#include "http_napi.h" -#include "napi_util.h" - -#include - -namespace OHOS { -namespace NetManagerStandard { -std::string URL_SEPARATOR = "?"; -std::string URL_DELIMITER = "&"; -constexpr int32_t HEADER_OFFSET = 2; - -HttpRequest::HttpRequest() -{ - headers_.clear(); - Initialize(); -} - -HttpRequest::~HttpRequest() -{ - curl_global_cleanup(); -} -/* - * Init curl all thread only - */ -bool HttpRequest::Initialize() -{ - std::lock_guard lock(mutex_); - if (initialized_) { - return true; - } - - if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { - NETMGR_LOGE("curl global init failed"); - return false; - } - return true; -} - -void HttpRequest::SetHeaders(std::string headersStr) -{ - if (headersStr.empty()) { - headers_.clear(); - return; - } - - const char separator = '\n'; - size_t posSeparator = headersStr.find(separator); - while (std::string::npos != posSeparator) { - std::string header = headersStr.substr(0, posSeparator - 1); - if (header == "") { - break; - } - size_t posColon = header.find(':'); - if (std::string::npos == posColon) { - headers_["null"] = "[\"" + header + "\"]"; - } else { - headers_["\"" + header.substr(0, posColon) + "\""] = "[\"" + header.substr(posColon - + HEADER_OFFSET) + "\"]"; - } - headersStr = headersStr.substr(posSeparator + 1); - posSeparator = headersStr.find(separator); - } -} - -void HttpRequest::SetHeader(CURL *curl) -{ - struct curl_slist *header = nullptr; - if (!headers_.empty()) { - std::map::iterator iter; - for (iter = headers_.begin(); iter != headers_.end(); iter++) { - header = curl_slist_append(header, (iter->first + ":" + iter->second).c_str()); - } - curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header); - } -} - -void HttpRequest::SetOptionURL(CURL *curl, HttpRequestOptionsContext *asyncContext) -{ - if (curl == nullptr || asyncContext == nullptr) { - NETMGR_LOGE("The parameter of curl or asyncContext is nullptr"); - return; - } - std::string url(asyncContext->GetUrl()); - - std::size_t index = url.find(URL_SEPARATOR); - std::string caFile(asyncContext->GetCaFile()); - bool isCaFile = IsCaFile(caFile); - if (index != std::string::npos) { - int32_t offset = url.rfind(URL_SEPARATOR); - std::string uri = url.substr(0, offset); - std::string param = url.substr(offset + 1); - - curl_easy_setopt(curl, CURLOPT_URL, uri.c_str()); - curl_easy_setopt(curl, CURLOPT_POSTFIELDS, param.c_str()); - curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, true); - curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); - if (url.substr(0, URL_PREFIX_LENGTH) == std::string("https://")) { - if (!isCaFile) { - curl_easy_setopt(curl, CURLOPT_CAINFO, "/etc/ssl/cacert.pem"); - } else { - curl_easy_setopt(curl, CURLOPT_CAINFO, caFile.c_str()); - } - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); - } - } else { - curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); - curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, true); - curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); - if (url.substr(0, URL_PREFIX_LENGTH) == std::string("https://")) { - if (!isCaFile) { - curl_easy_setopt(curl, CURLOPT_CAINFO, "/etc/ssl/cacert.pem"); - } else { - curl_easy_setopt(curl, CURLOPT_CAINFO, caFile.c_str()); - } - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); - } - } - - curl_easy_setopt(curl, CURLOPT_HEADER, 0L); - curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L); - curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L); - curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, asyncContext->GetConnectTimeout()); - curl_easy_setopt(curl, CURLOPT_TIMEOUT, asyncContext->GetReadTimeout()); -} - -void HttpRequest::SetMethod(CURL *curl, HttpRequestOptionsContext *asyncContext) -{ - if (curl == nullptr || asyncContext == nullptr) { - NETMGR_LOGE("The parameter of curl or asyncContext is nullptr"); - return; - } - RequestMethod method = asyncContext->GetRequestMethod(); - if (method == RequestMethod::OPTIONS || method == RequestMethod::GET || method == RequestMethod::HEAD - || method == RequestMethod::DELETE || method == RequestMethod::TRACE || method == RequestMethod::CONNECT) { - SetOptionForGet(curl, asyncContext); - } else if (method == RequestMethod::POST || method == RequestMethod::PUT) { - SetOptionForPost(curl, asyncContext); - } else { - NETMGR_LOGE("SetMethod ErrorCode : COMMON_ERROR_CODE"); - } -} - -bool HttpRequest::SetOptionForPost(CURL *curl, HttpRequestOptionsContext *asyncContext) -{ - if (curl == nullptr || asyncContext == nullptr) { - NETMGR_LOGE("The parameter of curl or asyncContext is nullptr"); - return false; - } - - CURLcode result = curl_easy_setopt(curl, CURLOPT_URL, asyncContext->GetUrl().c_str()); - if (result != CURLE_OK) { - NETMGR_LOGE("curl set option failed! error code %{public}d", result); - return false; - } - - result = curl_easy_setopt(curl, CURLOPT_POST, 1L); - if (result != CURLE_OK) { - NETMGR_LOGE("curl set option failed! error code %{public}d", result); - return false; - } - return true; -} - -bool HttpRequest::SetOptionForGet(CURL *curl, HttpRequestOptionsContext *asyncContext) -{ - if (curl == nullptr || asyncContext == nullptr) { - NETMGR_LOGE("The parameter of curl or asyncContext is nullptr"); - return false; - } - - std::string url(asyncContext->GetUrl()); - if (!asyncContext->GetExtraData().empty()) { - std::size_t index = url.find(URL_SEPARATOR); - if (index != std::string::npos) { - std::string param = url.substr(0, url.rfind(URL_SEPARATOR) + 1); - std::string encodeIn = param + URL_DELIMITER + asyncContext->GetExtraData(); - char *encodeOut = curl_easy_escape(curl, encodeIn.c_str(), 0); - if (encodeOut != nullptr) { - url = param + encodeOut; - curl_free(encodeOut); - } - } else { - char *encodeOut = curl_easy_escape(curl, asyncContext->GetExtraData().c_str(), 0); - if (encodeOut != nullptr) { - url = url + URL_SEPARATOR + encodeOut; - curl_free(encodeOut); - } - } - CURLcode result = curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); - if (result != CURLE_OK) { - NETMGR_LOGE("curl set option failed! error code %{public}d", result); - return false; - } - } else { - std::size_t index = url.find(URL_SEPARATOR); - if (index != std::string::npos) { - int32_t offset = url.rfind(URL_SEPARATOR); - std::string uri = url.substr(0, offset); - std::string param = url.substr(offset + 1); - curl_easy_setopt(curl, CURLOPT_URL, uri.c_str()); - curl_easy_setopt(curl, CURLOPT_POSTFIELDS, param.c_str()); - curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, true); - curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); - } - } - - return true; -} - -bool HttpRequest::GetCurlWriteData(HttpRequestOptionsContext *asyncContext) -{ - if (asyncContext == nullptr) { - return false; - } - - CURL *curl = curl_easy_init(); - if (curl == nullptr) { - NETMGR_LOGE("The parameter of curl is nullptr"); - return false; - } - SetOptionURL(curl, asyncContext); - - std::string responseBody; - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWritingMemoryBody); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, &responseBody); - - std::string responseHeader; - curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, OnWritingMemoryHeader); - curl_easy_setopt(curl, CURLOPT_HEADERDATA, &responseHeader); - curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl-agent/1.0"); - - int32_t responseCode; - curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &responseCode); - - CURLcode res = curl_easy_perform(curl); - if (res != CURLE_OK) { - NETMGR_LOGE("curl easy perform error : %{public}s, num: %{public}d", curl_easy_strerror(res), res); - curl_easy_cleanup(curl); - return false; - } - HttpResponse responseData = asyncContext->GetResponseData(); - responseData.SetResult(responseBody); - responseData.SetHeader(responseHeader); - responseData.SetResponseCode((enum ResponseCode)responseCode); - - asyncContext->SetResponseData(responseData); - EmitHeader(asyncContext->httpRequestInfo_, responseHeader); - - curl_easy_cleanup(curl); - return true; -} - -void HttpRequest::EmitHeader(HttpRequest *obj, const std::string &header) -{ - struct EventListener *eventListener = nullptr; - for (std::list::iterator listenerIterator = g_eventListenerList.begin(); - listenerIterator != g_eventListenerList.end(); ++listenerIterator) { - if (listenerIterator->httpRequestInfo_ == obj) { - struct EventListener eventListtmp = *listenerIterator; - eventListener = &eventListtmp; - napi_env env = listenerIterator->env_; - napi_handle_scope scope = nullptr; - napi_open_handle_scope(env, &scope); - napi_value undefine = nullptr; - napi_get_undefined(env, &undefine); - napi_ref callbackRef = listenerIterator->callbackRef_; - napi_value callbackFunc = nullptr; - napi_get_reference_value(env, callbackRef, &callbackFunc); - napi_value callbackValues[2] = {0}; - - callbackValues[0] = NapiUtil::CreateUndefined(env); - napi_value object = nullptr; - napi_create_object(env, &object); - NapiUtil::SetPropertyStringUtf8(env, object, "header", header); - - callbackValues[1] = object; - napi_value callbackResult = nullptr; - napi_call_function(env, undefine, callbackFunc, std::size(callbackValues), callbackValues, - &callbackResult); - napi_close_handle_scope(env, scope); - napi_delete_reference(env, listenerIterator->callbackRef_); - break; - } - } - if (eventListener != nullptr) { - g_eventListenerList.remove_if( - [obj](EventListener listener) -> bool { return listener.httpRequestInfo_ == obj; }); - } -} - -bool HttpRequest::NativeRequest(HttpRequestOptionsContext *asyncContext) -{ - return GetCurlWriteData(asyncContext); -} - -bool HttpRequest::IsCaFile(const std::string &caFile) -{ - if (caFile.empty()) { - return false; - } - if (access(caFile.c_str(), F_OK) == -1) { - return false; - } - return true; -} -} // namespace NetManagerStandard -} // namespace OHOS \ No newline at end of file diff --git a/frameworks/js/napi/http/src/napi_util.cpp b/frameworks/js/napi/http/src/napi_util.cpp deleted file mode 100644 index 1ec59253474c47b6348def7cf1ccefe59ebbf386..0000000000000000000000000000000000000000 --- a/frameworks/js/napi/http/src/napi_util.cpp +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Copyright (C) 2021 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 "napi_util.h" - -#include -#include - -#include "netmgr_log_wrapper.h" - -namespace OHOS { -namespace NetManagerStandard { -std::string NapiUtil::ToUtf8(std::u16string str16) -{ - return std::wstring_convert, char16_t> {}.to_bytes(str16); -} - -std::u16string NapiUtil::ToUtf16(std::string str) -{ - return std::wstring_convert, char16_t> {}.from_bytes(str); -} - -napi_value NapiUtil::CreateErrorMessage(napi_env env, std::string msg, int32_t errorCode) -{ - napi_value result = nullptr; - napi_value message = nullptr; - NAPI_CALL(env, napi_create_string_utf8(env, msg.c_str(), msg.length(), &message)); - napi_value codeValue = nullptr; - std::string errCode = std::to_string(errorCode); - NAPI_CALL(env, napi_create_string_utf8(env, errCode.c_str(), errCode.length(), &codeValue)); - NAPI_CALL(env, napi_create_error(env, codeValue, message, &result)); - return result; -} - -napi_value NapiUtil::CreateUndefined(napi_env env) -{ - napi_value result = nullptr; - NAPI_CALL(env, napi_get_undefined(env, &result)); - return result; -} - -bool NapiUtil::MatchValueType(napi_env env, napi_value value, napi_valuetype targetType) -{ - napi_valuetype valueType = napi_undefined; - NAPI_CALL_BASE(env, napi_typeof(env, value, &valueType), false); - return valueType == targetType; -} - -bool NapiUtil::MatchParameters( - napi_env env, const napi_value parameters[], std::initializer_list valueTypes) -{ - if (parameters == nullptr) { - return false; - } - int i = 0; - for (auto beg = valueTypes.begin(); beg != valueTypes.end(); ++beg) { - if (!MatchValueType(env, parameters[i], *beg)) { - return false; - } - ++i; - } - return true; -} - -void NapiUtil::SetPropertyInt32(napi_env env, napi_value object, std::string name, int32_t value) -{ - napi_value propertyValue = nullptr; - NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, value, &propertyValue)); - NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, object, name.c_str(), propertyValue)); -} - -void NapiUtil::SetPropertyStringUtf8(napi_env env, napi_value object, std::string name, std::string value) -{ - napi_value propertyValue = nullptr; - char *valueChars = (char *)value.c_str(); - NAPI_CALL_RETURN_VOID(env, napi_create_string_utf8(env, valueChars, std::strlen(valueChars), &propertyValue)); - NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, object, name.c_str(), propertyValue)); -} - -void NapiUtil::SetPropertyBoolean(napi_env env, napi_value object, std::string name, bool value) -{ - napi_value propertyValue = nullptr; - NAPI_CALL_RETURN_VOID(env, napi_get_boolean(env, value, &propertyValue)); - NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, object, name.c_str(), propertyValue)); -} - -napi_value NapiUtil::ToInt32Value(napi_env env, int32_t value) -{ - napi_value staticValue = nullptr; - NAPI_CALL(env, napi_create_int32(env, value, &staticValue)); - return staticValue; -} - -bool NapiUtil::HasNamedProperty(napi_env env, napi_value object, std::string propertyName) -{ - bool hasProperty = false; - NAPI_CALL_BASE(env, napi_has_named_property(env, object, propertyName.data(), &hasProperty), false); - return hasProperty; -} - -bool NapiUtil::HasNamedTypeProperty(napi_env env, napi_value object, napi_valuetype type, std::string propertyName) -{ - bool hasProperty = false; - NAPI_CALL_BASE(env, napi_has_named_property(env, object, propertyName.data(), &hasProperty), false); - if (hasProperty) { - napi_value value = nullptr; - NAPI_CALL_BASE(env, napi_get_named_property(env, object, propertyName.data(), &value), false); - return MatchValueType(env, value, type); - } - return false; -} - -bool NapiUtil::MatchObjectProperty( - napi_env env, napi_value object, std::initializer_list> pairList) -{ - if (object == nullptr) { - return false; - } - for (auto beg = pairList.begin(); beg != pairList.end(); ++beg) { - if (!HasNamedTypeProperty(env, object, beg->second, beg->first)) { - return false; - } - } - return true; -} - -bool NapiUtil::MatchOptionPropertyType( - napi_env env, napi_value object, napi_valuetype type, std::string propertyName) -{ - bool hasProperty = false; - NAPI_CALL_BASE(env, napi_has_named_property(env, object, propertyName.data(), &hasProperty), false); - if (hasProperty) { - napi_value value = nullptr; - NAPI_CALL_BASE(env, napi_get_named_property(env, object, propertyName.data(), &value), false); - return MatchValueType(env, value, type); - } - return true; -} - -std::string NapiUtil::GetStringFromValue(napi_env env, napi_value value) -{ - char msgChars[MAX_TEXT_LENGTH] = {0}; - size_t msgLength = 0; - NAPI_CALL_BASE(env, napi_get_value_string_utf8(env, value, msgChars, MAX_TEXT_LENGTH, &msgLength), ""); - if (msgLength > 0) { - return std::string(msgChars, 0, msgLength); - } else { - return ""; - } -} - -napi_value NapiUtil::GetNamedProperty(napi_env env, napi_value object, std::string propertyName) -{ - napi_value value = nullptr; - NAPI_CALL(env, napi_get_named_property(env, object, propertyName.data(), &value)); - return value; -} - -bool NapiUtil::MatchHttpRequestDataParameters(napi_env env, const napi_value parameters[], size_t parameterCount) -{ - switch (parameterCount) { - case SWITCH_PARAM_ZERO: - return true; - case SWITCH_PARAM_ONE: - return MatchParameters(env, parameters, {napi_string}); - case SWITCH_PARAM_TWO: - if (MatchParameters(env, parameters, {napi_string, napi_function}) - || MatchParameters(env, parameters, {napi_string, napi_object})) { - return true; - } - return false; - case SWITCH_PARAM_THREE: - return MatchParameters(env, parameters, {napi_string, napi_object, napi_function}); - default: - return false; - } -} - -bool NapiUtil::MatchHttpOnDataParameters(napi_env env, const napi_value parameters[], size_t parameterCount) -{ - switch (parameterCount) { - case SWITCH_PARAM_ZERO: - return true; - case SWITCH_PARAM_ONE: - return false; - case SWITCH_PARAM_TWO: - return MatchParameters(env, parameters, {napi_string, napi_function}); - default: - return false; - } -} - -bool NapiUtil::MatchHttpOffDataParameters(napi_env env, const napi_value parameters[], size_t parameterCount) -{ - switch (parameterCount) { - case SWITCH_PARAM_ZERO: - return true; - case SWITCH_PARAM_ONE: - return MatchParameters(env, parameters, {napi_string}); - case SWITCH_PARAM_TWO: - return MatchParameters(env, parameters, {napi_string, napi_function}); - default: - return false; - } -} - -void NapiUtil::SetPropertyArray(napi_env env, napi_value object, std::string name, std::vector pdu) -{ - napi_value array = nullptr; - napi_create_array(env, &array); - int size = pdu.size(); - for (int i = 0; i < size; i++) { - napi_value element = nullptr; - std::string tmp = pdu.at(i); - napi_create_string_utf8(env, tmp.c_str(), tmp.size(), &element); - napi_set_element(env, array, i, element); - } - napi_set_named_property(env, object, name.c_str(), array); -} - -int32_t NapiUtil::GetIntProperty(napi_env env, napi_value object, const std::string &propertyName) -{ - int32_t intValue = 0; - napi_value value = nullptr; - napi_status getNameStatus = napi_get_named_property(env, object, propertyName.c_str(), &value); - if (getNameStatus == napi_ok) { - napi_status getIntStatus = napi_get_value_int32(env, value, &intValue); - if (getIntStatus == napi_ok) { - return intValue; - } - } - return intValue; -} - -std::string NapiUtil::GetStringProperty(napi_env env, napi_value object, const std::string &propertyName) -{ - napi_value value = nullptr; - napi_status getNameStatus = napi_get_named_property(env, object, propertyName.c_str(), &value); - if (getNameStatus == napi_ok) { - char buf[maxUrlLength] = {0}; - size_t bufLength = 0; - napi_status getStringStatus = napi_get_value_string_utf8(env, value, buf, maxUrlLength, &bufLength); - if (getStringStatus == napi_ok && bufLength > 0) { - return std::string(buf, bufLength); - } - } - return ""; -} -} // namespace NetManagerStandard -} // namespace OHOS \ No newline at end of file diff --git a/frameworks/js/napi/socket/include/tcp_send_options.h b/frameworks/js/napi/socket/async_context/include/bind_context.h similarity index 46% rename from frameworks/js/napi/socket/include/tcp_send_options.h rename to frameworks/js/napi/socket/async_context/include/bind_context.h index 1bb4a59f903a47cbcd5f50ad03b5519da289797e..26b912a77931d607cbebf396f6120340766cbebf 100644 --- a/frameworks/js/napi/socket/include/tcp_send_options.h +++ b/frameworks/js/napi/socket/async_context/include/bind_context.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Huawei Device Co., Ltd. + * Copyright (C) 2021-2022 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 @@ -13,44 +13,34 @@ * limitations under the License. */ -#ifndef TCP_SEND_OPTIONS_H -#define TCP_SEND_OPTIONS_H +#ifndef COMMUNICATIONNETSTACK_BIND_CONTEXT_H +#define COMMUNICATIONNETSTACK_BIND_CONTEXT_H #include "napi/native_api.h" -#include "napi/native_node_api.h" +#include "net_address.h" +#include "netstack_base_context.h" +#include "noncopyable.h" -#include +namespace OHOS::NetStack { -namespace OHOS { -namespace NetManagerStandard { -class TCPSendOptions { +class BindContext final : public BaseContext { public: - TCPSendOptions() {} - ~TCPSendOptions() {} - - std::string GetData() - { - return data_; - } - - void SetData(std::string data) - { - this->data_ = data; - } - - std::string GetEncoding() - { - return encoding_; - } - - void SetEncoding(std::string encoding) - { - this->encoding_ = encoding; - } + ACE_DISALLOW_COPY_AND_MOVE(BindContext); + + BindContext() = delete; + + explicit BindContext(napi_env env, EventManager *manager); + + void ParseParams(napi_value *params, size_t paramsCount); + + [[nodiscard]] int GetSocketFd() const; + + NetAddress address; + private: - std::string data_ = ""; - std::string encoding_ = ""; + bool CheckParamsType(napi_value *params, size_t paramsCount); }; -} // namespace NetManagerStandard -} // namespace OHOS -#endif // TCP_SEND_OPTIONS_H \ No newline at end of file + +} // namespace OHOS::NetStack + +#endif /* COMMUNICATIONNETSTACK_BIND_CONTEXT_H */ diff --git a/frameworks/js/napi/socket/include/socket_remote_info.h b/frameworks/js/napi/socket/async_context/include/common_context.h similarity index 36% rename from frameworks/js/napi/socket/include/socket_remote_info.h rename to frameworks/js/napi/socket/async_context/include/common_context.h index f0c2710c88d950be91663155c57430466934a672..c5086035042c8790d766333d677b2ab8f56ca729 100644 --- a/frameworks/js/napi/socket/include/socket_remote_info.h +++ b/frameworks/js/napi/socket/async_context/include/common_context.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Huawei Device Co., Ltd. + * Copyright (C) 2021-2022 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 @@ -13,65 +13,52 @@ * limitations under the License. */ -#ifndef SOCKET_REMOTE_INFO_H -#define SOCKET_REMOTE_INFO_H +#ifndef COMMUNICATIONNETSTACK_COMMON_CONTEXT_H +#define COMMUNICATIONNETSTACK_COMMON_CONTEXT_H -#include "napi/native_api.h" -#include "napi/native_node_api.h" -#include "napi_util.h" +#include "netstack_base_context.h" +#include "netstack_event_manager.h" +#include "noncopyable.h" +#include "socket_remote_info.h" +#include "socket_state_base.h" -namespace OHOS { -namespace NetManagerStandard { -class SocketRemoteInfo { +namespace OHOS::NetStack { + +class CommonContext : public BaseContext { public: - SocketRemoteInfo() {} - ~SocketRemoteInfo() {} - - std::string GetAddress() - { - return address_; - } - - void SetAddress(const std::string& address) - { - this->address_ = address; - } - - std::string GetFamily() - { - return family_; - } - - void SetFamily(const std::string& family) - { - this->family_ = family; - } - - int32_t GetPort() - { - return port_; - } - - void SetPort(int32_t port) - { - this->port_ = port; - } - - int32_t GetSize() - { - return size_; - } - - void SetSize(int32_t size) - { - this->size_ = size; - } + ACE_DISALLOW_COPY_AND_MOVE(CommonContext); + + CommonContext() = delete; + + explicit CommonContext(napi_env env, EventManager *manager); + + void ParseParams(napi_value *params, size_t paramsCount); + + [[nodiscard]] int GetSocketFd() const; + + SocketStateBase state; + + NetAddress address; + private: - std::string address_ = ""; - std::string family_ = "IPv4"; - int32_t port_ = 0; - int32_t size_ = 0; + bool CheckParamsType(napi_value *params, size_t paramsCount); +}; + +typedef CommonContext GetStateContext; + +typedef CommonContext GetRemoteAddressContext; + +class CloseContext final : public CommonContext { +public: + ACE_DISALLOW_COPY_AND_MOVE(CloseContext); + + CloseContext() = delete; + + explicit CloseContext(napi_env env, EventManager *manager); + + void SetSocketFd(int sock); }; -} // namespace NetManagerStandard -} // namespace OHOS -#endif // SOCKET_REMOTE_INFO_H \ No newline at end of file + +} // namespace OHOS::NetStack + +#endif /* COMMUNICATIONNETSTACK_COMMON_CONTEXT_H */ diff --git a/frameworks/js/napi/socket/async_context/include/connect_context.h b/frameworks/js/napi/socket/async_context/include/connect_context.h new file mode 100644 index 0000000000000000000000000000000000000000..472e8b5b9065cd2118eadb91eed33ebbfc07247f --- /dev/null +++ b/frameworks/js/napi/socket/async_context/include/connect_context.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2021-2022 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_CONNECT_CONTEXT_H +#define COMMUNICATIONNETSTACK_CONNECT_CONTEXT_H + +#include "netstack_base_context.h" +#include "noncopyable.h" +#include "tcp_connect_options.h" + +namespace OHOS::NetStack { + +class ConnectContext final : public BaseContext { +public: + ACE_DISALLOW_COPY_AND_MOVE(ConnectContext); + + ConnectContext() = delete; + + explicit ConnectContext(napi_env env, EventManager *manager); + + void ParseParams(napi_value *params, size_t paramsCount); + + [[nodiscard]] int GetSocketFd() const; + + TcpConnectOptions options; + +private: + bool CheckParamsType(napi_value *params, size_t paramsCount); +}; + +} // namespace OHOS::NetStack + +#endif /* COMMUNICATIONNETSTACK_CONNECT_CONTEXT_H */ diff --git a/frameworks/js/napi/socket/include/tcp_connect_options.h b/frameworks/js/napi/socket/async_context/include/tcp_extra_context.h similarity index 42% rename from frameworks/js/napi/socket/include/tcp_connect_options.h rename to frameworks/js/napi/socket/async_context/include/tcp_extra_context.h index 31d9952d00abb6b29da972c59635d2541cc648be..d1521c9d953a2b004c0069909a0748836c1dd946 100644 --- a/frameworks/js/napi/socket/include/tcp_connect_options.h +++ b/frameworks/js/napi/socket/async_context/include/tcp_extra_context.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Huawei Device Co., Ltd. + * Copyright (C) 2021-2022 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 @@ -13,43 +13,33 @@ * limitations under the License. */ -#ifndef TCP_CONNECT_OPTIONS_H -#define TCP_CONNECT_OPTIONS_H +#ifndef COMMUNICATIONNETSTACK_TCP_EXTRA_CONTEXT_H +#define COMMUNICATIONNETSTACK_TCP_EXTRA_CONTEXT_H -#include "napi/native_api.h" -#include "napi/native_node_api.h" -#include "netaddress.h" +#include "netstack_base_context.h" +#include "noncopyable.h" +#include "tcp_extra_options.h" -namespace OHOS { -namespace NetManagerStandard { -class TCPConnectOptions { +namespace OHOS::NetStack { + +class TcpSetExtraOptionsContext : public BaseContext { public: - TCPConnectOptions() {} - ~TCPConnectOptions() {} - - struct NetAddress GetReceiveBufferSize() - { - return address_; - } - - void SetReceiveBufferSize(struct NetAddress address) - { - this->address_ = address; - } - - int32_t GetTimeout() - { - return timeout_; - } - - void SetTimeout(int32_t timeout) - { - this->timeout_ = timeout; - } + ACE_DISALLOW_COPY_AND_MOVE(TcpSetExtraOptionsContext); + + TcpSetExtraOptionsContext() = delete; + + explicit TcpSetExtraOptionsContext(napi_env env, EventManager *manager); + + void ParseParams(napi_value *params, size_t paramsCount); + + [[nodiscard]] int GetSocketFd() const; + + TCPExtraOptions options; + private: - struct NetAddress address_ = {}; - int32_t timeout_ = 0; + bool CheckParamsType(napi_value *params, size_t paramsCount); }; -} // namespace NetManagerStandard -} // namespace OHOS -#endif // TCP_CONNECT_OPTIONS_H \ No newline at end of file + +} // namespace OHOS::NetStack + +#endif /* COMMUNICATIONNETSTACK_TCP_EXTRA_CONTEXT_H */ 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 new file mode 100644 index 0000000000000000000000000000000000000000..bd97d78ef8d73ecdd5fccb5f86ccfefbd04b5313 --- /dev/null +++ b/frameworks/js/napi/socket/async_context/include/tcp_send_context.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2021-2022 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_TCP_SEND_CONTEXT_H +#define COMMUNICATIONNETSTACK_TCP_SEND_CONTEXT_H + +#include "netstack_base_context.h" +#include "noncopyable.h" +#include "tcp_send_options.h" + +namespace OHOS::NetStack { + +class TcpSendContext final : public BaseContext { +public: + ACE_DISALLOW_COPY_AND_MOVE(TcpSendContext); + + TcpSendContext() = delete; + + explicit TcpSendContext(napi_env env, EventManager *manager); + + void ParseParams(napi_value *params, size_t paramsCount); + + [[nodiscard]] int GetSocketFd() const; + + TCPSendOptions options; + +private: + bool CheckParamsType(napi_value *params, size_t paramsCount); + + bool GetData(napi_value udpSendOptions); +}; + +} // namespace OHOS::NetStack + +#endif /* COMMUNICATIONNETSTACK_TCP_SEND_CONTEXT_H */ diff --git a/frameworks/js/napi/socket/async_context/include/udp_extra_context.h b/frameworks/js/napi/socket/async_context/include/udp_extra_context.h new file mode 100644 index 0000000000000000000000000000000000000000..b10b144984e798f20ba795daaaeac48eafdd642c --- /dev/null +++ b/frameworks/js/napi/socket/async_context/include/udp_extra_context.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2021-2022 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_UDP_EXTRA_CONTEXT_H +#define COMMUNICATIONNETSTACK_UDP_EXTRA_CONTEXT_H + +#include "netstack_base_context.h" +#include "noncopyable.h" +#include "udp_extra_options.h" + +namespace OHOS::NetStack { + +class UdpSetExtraOptionsContext final : public BaseContext { +public: + ACE_DISALLOW_COPY_AND_MOVE(UdpSetExtraOptionsContext); + + UdpSetExtraOptionsContext() = delete; + + explicit UdpSetExtraOptionsContext(napi_env env, EventManager *manager); + + void ParseParams(napi_value *params, size_t paramsCount); + + [[nodiscard]] int GetSocketFd() const; + + UDPExtraOptions options; + +private: + bool CheckParamsType(napi_value *params, size_t paramsCount); +}; + +} // namespace OHOS::NetStack + +#endif /* COMMUNICATIONNETSTACK_UDP_EXTRA_CONTEXT_H */ 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 new file mode 100644 index 0000000000000000000000000000000000000000..0cbd33e9a589f590ad9d1efd02f2470637a12f98 --- /dev/null +++ b/frameworks/js/napi/socket/async_context/include/udp_send_context.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2021-2022 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_UDP_SEND_CONTEXT_H +#define COMMUNICATIONNETSTACK_UDP_SEND_CONTEXT_H + +#include "netstack_base_context.h" +#include "noncopyable.h" +#include "udp_send_options.h" + +namespace OHOS::NetStack { + +class UdpSendContext final : public BaseContext { +public: + ACE_DISALLOW_COPY_AND_MOVE(UdpSendContext); + + UdpSendContext() = delete; + + explicit UdpSendContext(napi_env env, EventManager *manager); + + void ParseParams(napi_value *params, size_t paramsCount); + + [[nodiscard]] int GetSocketFd() const; + + UDPSendOptions options; + +private: + bool CheckParamsType(napi_value *params, size_t paramsCount); + + bool GetData(napi_value udpSendOptions); +}; + +} // namespace OHOS::NetStack + +#endif /* COMMUNICATIONNETSTACK_UDP_SEND_CONTEXT_H */ diff --git a/frameworks/js/napi/socket/async_context/src/bind_context.cpp b/frameworks/js/napi/socket/async_context/src/bind_context.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8ddac48f87915a1a48e05d1bba86e2e5da3dc78b --- /dev/null +++ b/frameworks/js/napi/socket/async_context/src/bind_context.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2021-2022 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 "bind_context.h" + +#include "context_key.h" +#include "netstack_log.h" +#include "netstack_napi_utils.h" + +namespace OHOS::NetStack { + +BindContext::BindContext(napi_env env, EventManager *manager) : BaseContext(env, manager) {} + +void BindContext::ParseParams(napi_value *params, size_t paramsCount) +{ + bool valid = CheckParamsType(params, paramsCount); + if (!valid) { + return; + } + + std::string addr = NapiUtils::GetStringPropertyUtf8(GetEnv(), params[0], KEY_ADDRESS); + if (addr.empty()) { + NETSTACK_LOGE("address is empty"); + } + address.SetAddress(addr); + if (NapiUtils::HasNamedProperty(GetEnv(), params[0], KEY_FAMILY)) { + uint32_t family = NapiUtils::GetUint32Property(GetEnv(), params[0], KEY_FAMILY); + address.SetFamilyByJsValue(family); + } + if (NapiUtils::HasNamedProperty(GetEnv(), params[0], KEY_PORT)) { + uint16_t port = static_cast(NapiUtils::GetUint32Property(GetEnv(), params[0], KEY_PORT)); + address.SetPort(port); + } + + if (paramsCount == PARAM_OPTIONS_AND_CALLBACK) { + SetParseOK(SetCallback(params[1]) == napi_ok); + return; + } + SetParseOK(true); +} + +int BindContext::GetSocketFd() const +{ + return (int)(uint64_t)manager_->GetData(); +} + +bool BindContext::CheckParamsType(napi_value *params, size_t paramsCount) +{ + if (paramsCount == PARAM_JUST_OPTIONS) { + return NapiUtils::GetValueType(GetEnv(), params[0]) == napi_object; + } + + if (paramsCount == PARAM_OPTIONS_AND_CALLBACK) { + return NapiUtils::GetValueType(GetEnv(), params[0]) == napi_object && + NapiUtils::GetValueType(GetEnv(), params[1]) == napi_function; + } + return false; +} + +} // namespace OHOS::NetStack diff --git a/frameworks/js/napi/socket/async_context/src/common_context.cpp b/frameworks/js/napi/socket/async_context/src/common_context.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cea8d3a27902ddd79fd72d3f588641ac692c93bd --- /dev/null +++ b/frameworks/js/napi/socket/async_context/src/common_context.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2021-2022 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 "common_context.h" + +#include "context_key.h" +#include "netstack_napi_utils.h" + +namespace OHOS::NetStack { + +CommonContext::CommonContext(napi_env env, EventManager *manager) : BaseContext(env, manager) {} + +void CommonContext::ParseParams(napi_value *params, size_t paramsCount) +{ + bool valid = CheckParamsType(params, paramsCount); + if (!valid) { + return; + } + + if (paramsCount != PARAM_NONE) { + SetParseOK(SetCallback(params[0]) == napi_ok); + return; + } + SetParseOK(true); +} + +int CommonContext::GetSocketFd() const +{ + return (int)(uint64_t)manager_->GetData(); +} + +bool CommonContext::CheckParamsType(napi_value *params, size_t paramsCount) +{ + if (paramsCount == PARAM_NONE) { + return true; + } + + if (paramsCount == PARAM_JUST_CALLBACK) { + return NapiUtils::GetValueType(GetEnv(), params[0]) == napi_function; + } + return false; +} + +CloseContext::CloseContext(napi_env env, EventManager *manager) : CommonContext(env, manager) {} + +void CloseContext::SetSocketFd(int sock) +{ + manager_->SetData(reinterpret_cast(sock)); +} + +} // namespace OHOS::NetStack \ No newline at end of file diff --git a/frameworks/js/napi/socket/async_context/src/connect_context.cpp b/frameworks/js/napi/socket/async_context/src/connect_context.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f4b3cc42ef35f588a715d3dd1dbfa5457d4ebbbb --- /dev/null +++ b/frameworks/js/napi/socket/async_context/src/connect_context.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2021-2022 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 "connect_context.h" + +#include "context_key.h" +#include "netstack_log.h" +#include "netstack_napi_utils.h" +#include +namespace OHOS::NetStack { + +ConnectContext::ConnectContext(napi_env env, EventManager *manager) : BaseContext(env, manager) {} + +void ConnectContext::ParseParams(napi_value *params, size_t paramsCount) +{ + bool valid = CheckParamsType(params, paramsCount); + if (!valid) { + return; + } + + napi_value netAddress = NapiUtils::GetNamedProperty(GetEnv(), params[0], KEY_ADDRESS); + + std::string addr = NapiUtils::GetStringPropertyUtf8(GetEnv(), netAddress, KEY_ADDRESS); + if (addr.empty()) { + NETSTACK_LOGE("address is empty"); + } + options.address.SetAddress(addr); + if (NapiUtils::HasNamedProperty(GetEnv(), netAddress, KEY_FAMILY)) { + uint32_t family = NapiUtils::GetUint32Property(GetEnv(), netAddress, KEY_FAMILY); + options.address.SetFamilyByJsValue(family); + } + if (NapiUtils::HasNamedProperty(GetEnv(), netAddress, KEY_PORT)) { + uint16_t port = static_cast(NapiUtils::GetUint32Property(GetEnv(), netAddress, KEY_PORT)); + options.address.SetPort(port); + } + + uint32_t timeout = NapiUtils::GetUint32Property(GetEnv(), params[0], KEY_TIMEOUT); + if (timeout != 0) { + options.SetTimeout(timeout); + } + + if (paramsCount == PARAM_OPTIONS_AND_CALLBACK) { + SetParseOK(SetCallback(params[1]) == napi_ok); + return; + } + SetParseOK(true); +} + +int ConnectContext::GetSocketFd() const +{ + return (int)(uint64_t)manager_->GetData(); +} + +bool ConnectContext::CheckParamsType(napi_value *params, size_t paramsCount) +{ + if (paramsCount == PARAM_JUST_OPTIONS) { + return NapiUtils::GetValueType(GetEnv(), params[0]) == napi_object && + NapiUtils::GetValueType(GetEnv(), NapiUtils::GetNamedProperty(GetEnv(), params[0], KEY_ADDRESS)) == + napi_object; + } + + if (paramsCount == PARAM_OPTIONS_AND_CALLBACK) { + return NapiUtils::GetValueType(GetEnv(), params[0]) == napi_object && + NapiUtils::GetValueType(GetEnv(), NapiUtils::GetNamedProperty(GetEnv(), params[0], KEY_ADDRESS)) == + napi_object && + NapiUtils::GetValueType(GetEnv(), params[1]) == napi_function; + } + return false; +} + +} // namespace OHOS::NetStack \ No newline at end of file diff --git a/frameworks/js/napi/socket/async_context/src/tcp_extra_context.cpp b/frameworks/js/napi/socket/async_context/src/tcp_extra_context.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b0f917badcdd097a32011a0e4c256d2663c6150b --- /dev/null +++ b/frameworks/js/napi/socket/async_context/src/tcp_extra_context.cpp @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2021-2022 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 "tcp_extra_context.h" + +#include "context_key.h" +#include "netstack_napi_utils.h" + +namespace OHOS::NetStack { + +TcpSetExtraOptionsContext::TcpSetExtraOptionsContext(napi_env env, EventManager *manager) : BaseContext(env, manager) {} + +void TcpSetExtraOptionsContext::ParseParams(napi_value *params, size_t paramsCount) +{ + bool valid = CheckParamsType(params, paramsCount); + if (!valid) { + return; + } + + if (NapiUtils::HasNamedProperty(GetEnv(), params[0], KEY_RECEIVE_BUFFER_SIZE)) { + options.SetReceiveBufferSize(NapiUtils::GetUint32Property(GetEnv(), params[0], KEY_RECEIVE_BUFFER_SIZE)); + } + + if (NapiUtils::HasNamedProperty(GetEnv(), params[0], KEY_SEND_BUFFER_SIZE)) { + options.SetSendBufferSize(NapiUtils::GetUint32Property(GetEnv(), params[0], KEY_SEND_BUFFER_SIZE)); + } + + if (NapiUtils::HasNamedProperty(GetEnv(), params[0], KEY_REUSE_ADDRESS)) { + options.SetReuseAddress(NapiUtils::GetBooleanProperty(GetEnv(), params[0], KEY_REUSE_ADDRESS)); + } + + if (NapiUtils::HasNamedProperty(GetEnv(), params[0], KEY_SOCKET_TIMEOUT)) { + options.SetSocketTimeout(NapiUtils::GetUint32Property(GetEnv(), params[0], KEY_SOCKET_TIMEOUT)); + } + + if (NapiUtils::HasNamedProperty(GetEnv(), params[0], KEY_KEEP_ALIVE)) { + options.SetKeepAlive(NapiUtils::GetBooleanProperty(GetEnv(), params[0], KEY_KEEP_ALIVE)); + } + + if (NapiUtils::HasNamedProperty(GetEnv(), params[0], KEY_OOB_INLINE)) { + options.SetOOBInline(NapiUtils::GetBooleanProperty(GetEnv(), params[0], KEY_OOB_INLINE)); + } + + if (NapiUtils::HasNamedProperty(GetEnv(), params[0], KEY_TCP_NO_DELAY)) { + options.SetTCPNoDelay(NapiUtils::GetBooleanProperty(GetEnv(), params[0], KEY_TCP_NO_DELAY)); + } + + if (NapiUtils::HasNamedProperty(GetEnv(), params[0], KEY_SOCKET_LINGER)) { + napi_value socketLinger = NapiUtils::GetNamedProperty(GetEnv(), params[0], KEY_SOCKET_LINGER); + if (NapiUtils::GetValueType(GetEnv(), params[0]) == napi_object) { + if (NapiUtils::HasNamedProperty(GetEnv(), socketLinger, KEY_SOCKET_LINGER_ON)) { + options.socketLinger.SetOn(NapiUtils::GetBooleanProperty(GetEnv(), socketLinger, KEY_SOCKET_LINGER_ON)); + } + if (NapiUtils::HasNamedProperty(GetEnv(), socketLinger, KEY_SOCKET_LINGER_LINGER)) { + options.socketLinger.SetLinger( + NapiUtils::GetUint32Property(GetEnv(), socketLinger, KEY_SOCKET_LINGER_LINGER)); + } + } + } + + if (paramsCount == PARAM_OPTIONS_AND_CALLBACK) { + SetParseOK(SetCallback(params[1]) == napi_ok); + return; + } + SetParseOK(true); +} + +int TcpSetExtraOptionsContext::GetSocketFd() const +{ + return (int)(uint64_t)manager_->GetData(); +} + +bool TcpSetExtraOptionsContext::CheckParamsType(napi_value *params, size_t paramsCount) +{ + if (paramsCount == PARAM_JUST_OPTIONS) { + return NapiUtils::GetValueType(GetEnv(), params[0]) == napi_object; + } + + if (paramsCount == PARAM_OPTIONS_AND_CALLBACK) { + return NapiUtils::GetValueType(GetEnv(), params[0]) == napi_object && + NapiUtils::GetValueType(GetEnv(), params[1]) == napi_function; + } + return false; +} + +} // namespace OHOS::NetStack \ No newline at end of file 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 new file mode 100644 index 0000000000000000000000000000000000000000..fb98978bc64996f9e57375690e9eef81e01a7c39 --- /dev/null +++ b/frameworks/js/napi/socket/async_context/src/tcp_send_context.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2021-2022 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 "tcp_send_context.h" + +#include "context_key.h" +#include "netstack_log.h" +#include "netstack_napi_utils.h" +#include + +namespace OHOS::NetStack { + +TcpSendContext::TcpSendContext(napi_env env, EventManager *manager) : BaseContext(env, manager) {} + +void TcpSendContext::ParseParams(napi_value *params, size_t paramsCount) +{ + bool valid = CheckParamsType(params, paramsCount); + if (!valid) { + return; + } + + if (NapiUtils::HasNamedProperty(GetEnv(), params[0], KEY_ENCODING)) { + std::string encoding = NapiUtils::GetStringPropertyUtf8(GetEnv(), params[0], KEY_ENCODING); + options.SetEncoding(encoding); + } + if (!GetData(params[0])) { + return; + } + + if (paramsCount == PARAM_OPTIONS_AND_CALLBACK) { + SetParseOK(SetCallback(params[1]) == napi_ok); + return; + } + SetParseOK(true); +} + +int TcpSendContext::GetSocketFd() const +{ + return (int)(uint64_t)manager_->GetData(); +} + +bool TcpSendContext::CheckParamsType(napi_value *params, size_t paramsCount) +{ + if (paramsCount == PARAM_JUST_OPTIONS) { + return NapiUtils::GetValueType(GetEnv(), params[0]) == napi_object; + } + + if (paramsCount == PARAM_OPTIONS_AND_CALLBACK) { + return NapiUtils::GetValueType(GetEnv(), params[0]) == napi_object && + NapiUtils::GetValueType(GetEnv(), params[1]) == napi_function; + } + return false; +} + +bool TcpSendContext::GetData(napi_value udpSendOptions) +{ + napi_value jsData = NapiUtils::GetNamedProperty(GetEnv(), udpSendOptions, KEY_DATA); + if (NapiUtils::GetValueType(GetEnv(), jsData) == napi_string) { + std::string data = NapiUtils::GetStringFromValueUtf8(GetEnv(), jsData); + if (data.empty()) { + NETSTACK_LOGE("string data is empty"); + return false; + } + options.SetData(data); + return true; + } + + if (NapiUtils::ValueIsArrayBuffer(GetEnv(), jsData)) { + size_t length = 0; + void *data = NapiUtils::GetInfoFromArrayBufferValue(GetEnv(), jsData, &length); + if (data == nullptr) { + NETSTACK_LOGE("arraybuffer data is empty"); + return false; + } + options.SetData(data, length); + return true; + } + return false; +} + +} // namespace OHOS::NetStack \ No newline at end of file diff --git a/frameworks/js/napi/socket/async_context/src/udp_extra_context.cpp b/frameworks/js/napi/socket/async_context/src/udp_extra_context.cpp new file mode 100644 index 0000000000000000000000000000000000000000..695e35581ed247533090660e7d160b67ee55f93b --- /dev/null +++ b/frameworks/js/napi/socket/async_context/src/udp_extra_context.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2021-2022 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 "udp_extra_context.h" + +#include "context_key.h" +#include "netstack_napi_utils.h" + +namespace OHOS::NetStack { + +UdpSetExtraOptionsContext::UdpSetExtraOptionsContext(napi_env env, EventManager *manager) : BaseContext(env, manager) {} + +void UdpSetExtraOptionsContext::ParseParams(napi_value *params, size_t paramsCount) +{ + bool valid = CheckParamsType(params, paramsCount); + if (!valid) { + return; + } + + if (NapiUtils::HasNamedProperty(GetEnv(), params[0], KEY_RECEIVE_BUFFER_SIZE)) { + options.SetReceiveBufferSize(NapiUtils::GetUint32Property(GetEnv(), params[0], KEY_RECEIVE_BUFFER_SIZE)); + } + + if (NapiUtils::HasNamedProperty(GetEnv(), params[0], KEY_SEND_BUFFER_SIZE)) { + options.SetSendBufferSize(NapiUtils::GetUint32Property(GetEnv(), params[0], KEY_SEND_BUFFER_SIZE)); + } + + if (NapiUtils::HasNamedProperty(GetEnv(), params[0], KEY_REUSE_ADDRESS)) { + options.SetReuseAddress(NapiUtils::GetBooleanProperty(GetEnv(), params[0], KEY_REUSE_ADDRESS)); + } + + if (NapiUtils::HasNamedProperty(GetEnv(), params[0], KEY_SOCKET_TIMEOUT)) { + options.SetSocketTimeout(NapiUtils::GetUint32Property(GetEnv(), params[0], KEY_SOCKET_TIMEOUT)); + } + + if (NapiUtils::HasNamedProperty(GetEnv(), params[0], KEY_BROADCAST)) { + options.SetBroadcast(NapiUtils::GetUint32Property(GetEnv(), params[0], KEY_BROADCAST)); + } + + if (paramsCount == PARAM_OPTIONS_AND_CALLBACK) { + SetParseOK(SetCallback(params[1]) == napi_ok); + return; + } + SetParseOK(true); +} + +int UdpSetExtraOptionsContext::GetSocketFd() const +{ + return (int)(uint64_t)manager_->GetData(); +} + +bool UdpSetExtraOptionsContext::CheckParamsType(napi_value *params, size_t paramsCount) +{ + if (paramsCount == PARAM_JUST_OPTIONS) { + return NapiUtils::GetValueType(GetEnv(), params[0]) == napi_object; + } + + if (paramsCount == PARAM_OPTIONS_AND_CALLBACK) { + return NapiUtils::GetValueType(GetEnv(), params[0]) == napi_object && + NapiUtils::GetValueType(GetEnv(), params[1]) == napi_function; + } + return false; +} + +} // namespace OHOS::NetStack \ No newline at end of file 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 new file mode 100644 index 0000000000000000000000000000000000000000..841da1407797575c5a4e453ea68e21117baddb27 --- /dev/null +++ b/frameworks/js/napi/socket/async_context/src/udp_send_context.cpp @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2021-2022 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 "udp_send_context.h" + +#include "context_key.h" +#include "netstack_log.h" +#include "netstack_napi_utils.h" +#include + +namespace OHOS::NetStack { + +UdpSendContext::UdpSendContext(napi_env env, EventManager *manager) : BaseContext(env, manager) {} + +void UdpSendContext::ParseParams(napi_value *params, size_t paramsCount) +{ + bool valid = CheckParamsType(params, paramsCount); + if (!valid) { + return; + } + + napi_value netAddress = NapiUtils::GetNamedProperty(GetEnv(), params[0], KEY_ADDRESS); + + std::string addr = NapiUtils::GetStringPropertyUtf8(GetEnv(), netAddress, KEY_ADDRESS); + if (addr.empty()) { + NETSTACK_LOGE("address is empty"); + } + options.address.SetAddress(addr); + if (NapiUtils::HasNamedProperty(GetEnv(), netAddress, KEY_FAMILY)) { + uint32_t family = NapiUtils::GetUint32Property(GetEnv(), netAddress, KEY_FAMILY); + options.address.SetFamilyByJsValue(family); + } + if (NapiUtils::HasNamedProperty(GetEnv(), netAddress, KEY_PORT)) { + uint16_t port = static_cast(NapiUtils::GetUint32Property(GetEnv(), netAddress, KEY_PORT)); + options.address.SetPort(port); + } + if (!GetData(params[0])) { + return; + } + + if (paramsCount == PARAM_OPTIONS_AND_CALLBACK) { + SetParseOK(SetCallback(params[1]) == napi_ok); + return; + } + SetParseOK(true); +} + +int UdpSendContext::GetSocketFd() const +{ + return (int)(uint64_t)manager_->GetData(); +} + +bool UdpSendContext::CheckParamsType(napi_value *params, size_t paramsCount) +{ + if (paramsCount == PARAM_JUST_OPTIONS) { + return NapiUtils::GetValueType(GetEnv(), params[0]) == napi_object && + NapiUtils::GetValueType(GetEnv(), NapiUtils::GetNamedProperty(GetEnv(), params[0], KEY_ADDRESS)) == + napi_object; + } + + if (paramsCount == PARAM_OPTIONS_AND_CALLBACK) { + return NapiUtils::GetValueType(GetEnv(), params[0]) == napi_object && + NapiUtils::GetValueType(GetEnv(), NapiUtils::GetNamedProperty(GetEnv(), params[0], KEY_ADDRESS)) == + napi_object && + NapiUtils::GetValueType(GetEnv(), params[1]) == napi_function; + } + return false; +} + +bool UdpSendContext::GetData(napi_value udpSendOptions) +{ + napi_value jsData = NapiUtils::GetNamedProperty(GetEnv(), udpSendOptions, KEY_DATA); + if (NapiUtils::GetValueType(GetEnv(), jsData) == napi_string) { + std::string data = NapiUtils::GetStringFromValueUtf8(GetEnv(), jsData); + if (data.empty()) { + NETSTACK_LOGE("string data is empty"); + return false; + } + options.SetData(data); + return true; + } + + if (NapiUtils::ValueIsArrayBuffer(GetEnv(), jsData)) { + size_t length = 0; + void *data = NapiUtils::GetInfoFromArrayBufferValue(GetEnv(), jsData, &length); + if (data == nullptr) { + NETSTACK_LOGE("arraybuffer data is empty"); + return false; + } + options.SetData(data, length); + return true; + } + return false; +} + +} // namespace OHOS::NetStack 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 new file mode 100644 index 0000000000000000000000000000000000000000..ec54668c84b79c790ff0f8f595f30ff567ab5752 --- /dev/null +++ b/frameworks/js/napi/socket/async_work/include/socket_async_work.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2021-2022 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_SOCKET_ASYNC_WORK_H +#define COMMUNICATIONNETSTACK_SOCKET_ASYNC_WORK_H + +#include "napi/native_api.h" +#include "noncopyable.h" + +namespace OHOS::NetStack { + +class SocketAsyncWork final { +public: + ACE_DISALLOW_COPY_AND_MOVE(SocketAsyncWork); + + /* executor */ + static void ExecBind(napi_env env, void *data); + + static void ExecUdpSend(napi_env env, void *data); + + static void ExecConnect(napi_env env, void *data); + + static void ExecTcpSend(napi_env env, void *data); + + static void ExecClose(napi_env env, void *data); + + static void ExecGetState(napi_env env, void *data); + + static void ExecGetRemoteAddress(napi_env env, void *data); + + static void ExecTcpSetExtraOptions(napi_env env, void *data); + + static void ExecUdpSetExtraOptions(napi_env env, void *data); + + /* callback */ + static void BindCallback(napi_env env, napi_status status, void *data); + + static void UdpSendCallback(napi_env env, napi_status status, void *data); + + static void ConnectCallback(napi_env env, napi_status status, void *data); + + static void TcpSendCallback(napi_env env, napi_status status, void *data); + + static void CloseCallback(napi_env env, napi_status status, void *data); + + static void GetStateCallback(napi_env env, napi_status status, void *data); + + static void GetRemoteAddressCallback(napi_env env, napi_status status, void *data); + + static void TcpSetExtraOptionsCallback(napi_env env, napi_status status, void *data); + + static void UdpSetExtraOptionsCallback(napi_env env, napi_status status, void *data); +}; + +} // namespace OHOS::NetStack + +#endif /* COMMUNICATIONNETSTACK_SOCKET_ASYNC_WORK_H */ 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 new file mode 100644 index 0000000000000000000000000000000000000000..e86a944f8b35b86405028cca792e4bf2390f66c6 --- /dev/null +++ b/frameworks/js/napi/socket/async_work/src/socket_async_work.cpp @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2021-2022 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 "socket_async_work.h" + +#include "netstack_base_async_work.h" +#include "socket_exec.h" + +namespace OHOS::NetStack { + +void SocketAsyncWork::ExecBind(napi_env env, void *data) +{ + BaseAsyncWork::ExecAsyncWork(env, data); +} + +void SocketAsyncWork::ExecUdpSend(napi_env env, void *data) +{ + BaseAsyncWork::ExecAsyncWork(env, data); +} + +void SocketAsyncWork::ExecConnect(napi_env env, void *data) +{ + BaseAsyncWork::ExecAsyncWork(env, data); +} + +void SocketAsyncWork::ExecClose(napi_env env, void *data) +{ + BaseAsyncWork::ExecAsyncWork(env, data); +} + +void SocketAsyncWork::ExecTcpSend(napi_env env, void *data) +{ + BaseAsyncWork::ExecAsyncWork(env, data); +} + +void SocketAsyncWork::ExecGetState(napi_env env, void *data) +{ + BaseAsyncWork::ExecAsyncWork(env, data); +} + +void SocketAsyncWork::ExecGetRemoteAddress(napi_env env, void *data) +{ + BaseAsyncWork::ExecAsyncWork(env, data); +} + +void SocketAsyncWork::ExecTcpSetExtraOptions(napi_env env, void *data) +{ + BaseAsyncWork::ExecAsyncWork(env, data); +} + +void SocketAsyncWork::ExecUdpSetExtraOptions(napi_env env, void *data) +{ + BaseAsyncWork::ExecAsyncWork(env, data); +} + +void SocketAsyncWork::BindCallback(napi_env env, napi_status status, void *data) +{ + BaseAsyncWork::AsyncWorkCallback(env, status, data); +} + +void SocketAsyncWork::UdpSendCallback(napi_env env, napi_status status, void *data) +{ + BaseAsyncWork::AsyncWorkCallback(env, status, data); +} + +void SocketAsyncWork::ConnectCallback(napi_env env, napi_status status, void *data) +{ + BaseAsyncWork::AsyncWorkCallback(env, status, data); +} + +void SocketAsyncWork::TcpSendCallback(napi_env env, napi_status status, void *data) +{ + BaseAsyncWork::AsyncWorkCallback(env, status, data); +} + +void SocketAsyncWork::CloseCallback(napi_env env, napi_status status, void *data) +{ + BaseAsyncWork::AsyncWorkCallback(env, status, data); +} + +void SocketAsyncWork::GetStateCallback(napi_env env, napi_status status, void *data) +{ + BaseAsyncWork::AsyncWorkCallback(env, status, data); +} + +void SocketAsyncWork::GetRemoteAddressCallback(napi_env env, napi_status status, void *data) +{ + BaseAsyncWork::AsyncWorkCallback(env, status, data); +} + +void SocketAsyncWork::TcpSetExtraOptionsCallback(napi_env env, napi_status status, void *data) +{ + BaseAsyncWork::AsyncWorkCallback(env, status, + data); +} + +void SocketAsyncWork::UdpSetExtraOptionsCallback(napi_env env, napi_status status, void *data) +{ + BaseAsyncWork::AsyncWorkCallback(env, status, + data); +} + +} // namespace OHOS::NetStack \ No newline at end of file diff --git a/frameworks/js/napi/socket/constant/include/context_key.h b/frameworks/js/napi/socket/constant/include/context_key.h new file mode 100644 index 0000000000000000000000000000000000000000..4044948299814b2852b5ee015f6d0649476f44e1 --- /dev/null +++ b/frameworks/js/napi/socket/constant/include/context_key.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2021-2022 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_CONTEXT_KEY_H +#define COMMUNICATIONNETSTACK_CONTEXT_KEY_H + +#define KEY_ADDRESS "address" + +#define KEY_FAMILY "family" + +#define KEY_PORT "port" + +#define KEY_TIMEOUT "timeout" + +#define KEY_ENCODING "encoding" + +#define KEY_DATA "data" + +#define KEY_RECEIVE_BUFFER_SIZE "receiveBufferSize" + +#define KEY_SEND_BUFFER_SIZE "sendBufferSize" + +#define KEY_REUSE_ADDRESS "reuseAddress" + +#define KEY_SOCKET_TIMEOUT "socketTimeout" + +#define KEY_BROADCAST "broadcast" + +#define KEY_IS_BOUND "isBound" + +#define KEY_IS_CLOSE "isClose" + +#define KEY_IS_CONNECTED "isConnected" + +#define KEY_SIZE "size" + +#define KEY_KEEP_ALIVE "keepAlive" + +#define KEY_OOB_INLINE "OOBInline" + +#define KEY_TCP_NO_DELAY "TCPNoDelay" + +#define KEY_SOCKET_LINGER "socketLinger" + +#define KEY_SOCKET_LINGER_ON "on" + +#define KEY_SOCKET_LINGER_LINGER "linger" + +#define KEY_ERROR_CODE "code" + +#define KEY_MESSAGE "message" + +#define KEY_REMOTE_INFO "remoteInfo" + +#define PARAM_NONE 0 + +#define PARAM_JUST_OPTIONS 1 + +#define PARAM_JUST_CALLBACK 1 + +#define PARAM_OPTIONS_AND_CALLBACK 2 + +#endif /* COMMUNICATIONNETSTACK_CONTEXT_KEY_H */ diff --git a/frameworks/js/napi/socket/include/tcp_event_list.h b/frameworks/js/napi/socket/constant/include/event_list.h similarity index 55% rename from frameworks/js/napi/socket/include/tcp_event_list.h rename to frameworks/js/napi/socket/constant/include/event_list.h index 5672d9bcc722cc7fa5ccc7f9ae6ea9c085dfc62f..f44b03d86c27393991b914af102f3b534a50b4f4 100644 --- a/frameworks/js/napi/socket/include/tcp_event_list.h +++ b/frameworks/js/napi/socket/constant/include/event_list.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Huawei Device Co., Ltd. + * Copyright (C) 2021-2022 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 @@ -13,22 +13,15 @@ * limitations under the License. */ -#ifndef TCP_EVENT_LIST_H -#define TCP_EVENT_LIST_H +#ifndef COMMUNICATIONNETSTACK_EVENT_LIST_H +#define COMMUNICATIONNETSTACK_EVENT_LIST_H -#include "napi/native_api.h" -#include "napi/native_node_api.h" +#define EVENT_MESSAGE "message" -namespace OHOS { -namespace NetManagerStandard { -class TCPSocket; -struct TcpEventListener { - napi_env env_; - int32_t eventType_; - bool isOnce_; - napi_ref callbackRef_; - TCPSocket *tcpSocket_; -}; -} // namespace NetManagerStandard -} // namespace OHOS -#endif // TCP_EVENT_LIST_H \ No newline at end of file +#define EVENT_LISTENING "listening" + +#define EVENT_ERROR "error" + +#define EVENT_CONNECT "connect" + +#endif /* COMMUNICATIONNETSTACK_EVENT_LIST_H */ diff --git a/frameworks/js/napi/socket/include/extra_options_base.h b/frameworks/js/napi/socket/include/extra_options_base.h deleted file mode 100644 index 2c434e01f8679aa03db06c8f8deff150b082148e..0000000000000000000000000000000000000000 --- a/frameworks/js/napi/socket/include/extra_options_base.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2021 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 EXTRA_OPTIONS_BASE_H -#define EXTRA_OPTIONS_BASE_H - -#include "napi/native_api.h" -#include "napi/native_node_api.h" -#include "napi_util.h" - -namespace OHOS { -namespace NetManagerStandard { -class ExtraOptionsBase { -public: - ExtraOptionsBase() {} - ~ExtraOptionsBase() {} - - int32_t GetReceiveBufferSize() - { - return receiveBufferSize_; - } - - void SetReceiveBufferSize(int32_t receiveBufferSize) - { - this->receiveBufferSize_ = receiveBufferSize; - } - - int32_t GetSendBufferSize() - { - return sendBufferSize_; - } - - void SetSendBufferSize(int32_t sendBufferSize) - { - this->sendBufferSize_ = sendBufferSize; - } - - int32_t GetReuseAddress() - { - return reuseAddress_; - } - - void SetReuseAddress(int32_t reuseAddress) - { - this->reuseAddress_ = reuseAddress; - } - - int32_t GetSocketTimeout() - { - return socketTimeout_; - } - - void SetSocketTimeout(int32_t socketTimeout) - { - this->socketTimeout_ = socketTimeout; - } -private: - int32_t receiveBufferSize_ = 0; - int32_t sendBufferSize_ = 0; - int32_t reuseAddress_ = 0; - int32_t socketTimeout_ = 0; -}; -} // namespace NetManagerStandard -} // namespace OHOS -#endif // EXTRA_OPTIONS_BASE_H \ No newline at end of file diff --git a/frameworks/js/napi/socket/include/socket_base_context.h b/frameworks/js/napi/socket/include/socket_base_context.h deleted file mode 100644 index e5114ecd8e09d244916d4d766390e2a6c907765c..0000000000000000000000000000000000000000 --- a/frameworks/js/napi/socket/include/socket_base_context.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2021 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 SOCKET_BASE_CONTEXT_H -#define SOCKET_BASE_CONTEXT_H - -#include "napi/native_api.h" -#include "napi/native_node_api.h" -#include "napi_util.h" - -namespace OHOS { -namespace NetManagerStandard { -class SocketBaseContext { -public: - napi_async_work work_ = nullptr; - napi_deferred deferred_ = nullptr; - napi_ref callbackRef_ = nullptr; - int32_t errorCode_ = ERROR_DEFAULT; - bool resolved_ = false; - napi_value result_ = 0; - bool isCallback_ = false; -public: - SocketBaseContext() {} - ~SocketBaseContext() {} -}; -} // namespace NetManagerStandard -} // namespace OHOS -#endif // SOCKET_BASE_CONTEXT_H \ No newline at end of file diff --git a/frameworks/js/napi/socket/include/socket_napi.h b/frameworks/js/napi/socket/include/socket_napi.h deleted file mode 100644 index 4ffc39799a46cbfe9ea2b3025e19fb2c74d3927e..0000000000000000000000000000000000000000 --- a/frameworks/js/napi/socket/include/socket_napi.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2021 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 SOCKET_NAPI_H -#define SOCKET_NAPI_H - -#include "sys/socket.h" -#include "unistd.h" -#include "sys/socket.h" -#include "napi/native_api.h" -#include "napi/native_node_api.h" -#include "tcp_event_list.h" -#include "udp_event_list.h" - -#include -#include -#include -#include -#include - -namespace OHOS { -namespace NetManagerStandard { - const int32_t ERROR_NONE = 0; - const int32_t ERROR_SERVICE_UNAVAILABLE = -2; - const int32_t ERROR_PARAMETER_VALUE_INVALID = -3; - const int32_t ERROR_NATIVE_API_EXECUTE_FAIL = -4; - const int32_t NORMAL_STRING_SIZE = 64; - constexpr int32_t PARAMS_COUNT = 2; - - static const std::int32_t STR_MAX_SIZE = 64; - static const std::int32_t PORT_MIN_SIZE = 0; - static const std::int32_t PORT_MAX_SIZE = 65535; - static const std::int32_t defaultValue = -1; - - static std::list g_udpEventListenerList; - static std::list g_tcpEventListenerList; - - // UDP extern interface - napi_value CreateUDPSocket(napi_env env, napi_callback_info info); - napi_value UdpBind(napi_env env, napi_callback_info info); - napi_value UdpConnect(napi_env env, napi_callback_info info); - napi_value UdpSend(napi_env env, napi_callback_info info); - napi_value UdpClose(napi_env env, napi_callback_info info); - napi_value UdpGetState(napi_env env, napi_callback_info info); - napi_value UdpSetExtraOptions(napi_env env, napi_callback_info info); - napi_value UdpOn(napi_env env, napi_callback_info info); - napi_value UdpOff(napi_env env, napi_callback_info info); - // TCP extern interface - napi_value CreateTCPSocket(napi_env env, napi_callback_info info); - napi_value TcpBind(napi_env env, napi_callback_info info); - napi_value TcpConnect(napi_env env, napi_callback_info info); - napi_value TcpSend(napi_env env, napi_callback_info info); - napi_value TcpClose(napi_env env, napi_callback_info info); - napi_value TcpGetRemoteAddress(napi_env env, napi_callback_info info); - napi_value TcpGetState(napi_env env, napi_callback_info info); - napi_value TcpSetExtraOptions(napi_env env, napi_callback_info info); - napi_value TcpOn(napi_env env, napi_callback_info info); - napi_value TcpOff(napi_env env, napi_callback_info info); -} // namespace NetManagerStandard -} // namespace OHOS -#endif // SOCKET_NAPI_H \ No newline at end of file diff --git a/frameworks/js/napi/socket/include/tcp_extra_options.h b/frameworks/js/napi/socket/include/tcp_extra_options.h deleted file mode 100644 index c184f7448388837ca4ef3092c0ed4b8dee0536a7..0000000000000000000000000000000000000000 --- a/frameworks/js/napi/socket/include/tcp_extra_options.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2021 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 TCP_EXTRA_OPTIONS_H -#define TCP_EXTRA_OPTIONS_H - -#include "napi/native_api.h" -#include "napi/native_node_api.h" -#include "extra_options_base.h" - -namespace OHOS { -namespace NetManagerStandard { -class TCPExtraOptions : public ExtraOptionsBase { -public: - TCPExtraOptions() {} - ~TCPExtraOptions() {} - - class SocketLinger { - public: - bool on_ = true; - int32_t linger_ = 0; - } socketLinger_; - - bool GetKeepAlive() - { - return keepAlive_; - } - - void SetKeepAlive(bool keepAlive) - { - this->keepAlive_ = keepAlive; - } - - bool GetOOBInline() - { - return OOBInline_; - } - - void SetOOBInline(bool OOBInline) - { - this->OOBInline_ = OOBInline; - } - - bool GetTCPNoDelay() - { - return TCPNoDelay_; - } - - void SetTCPNoDelay(bool TCPNoDelay) - { - this->TCPNoDelay_ = TCPNoDelay; - } - - bool GetSocketLingerOn() - { - return socketLinger_.on_; - } - - void SetSocketLingerOn(bool on) - { - this->socketLinger_.on_ = on; - } - - int32_t GetSocketLingerLinger() - { - return socketLinger_.linger_; - } - - void SetSocketLingerLinger(int32_t linger) - { - this->socketLinger_.linger_ = linger; - } -private: - bool keepAlive_ = false; - bool OOBInline_ = false; - bool TCPNoDelay_ = false; -}; -} // namespace NetManagerStandard -} // namespace OHOS -#endif // TCP_EXTRA_OPTIONS_H \ No newline at end of file diff --git a/frameworks/js/napi/socket/include/tcp_socket.h b/frameworks/js/napi/socket/include/tcp_socket.h deleted file mode 100644 index 49289f798818dda234f07a9d544a619428436b4b..0000000000000000000000000000000000000000 --- a/frameworks/js/napi/socket/include/tcp_socket.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2021 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 TCP_SOCKET_H -#define TCP_SOCKET_H - -#include "sys/socket.h" -#include "unistd.h" -#include "sys/socket.h" -#include "napi/native_api.h" -#include "napi/native_node_api.h" -#include "netaddress.h" -#include "socket_napi.h" -#include "tcp_extra_options.h" - -#include -#include -#include -#include - -namespace OHOS { -namespace NetManagerStandard { -class TCPSocket; -struct TcpBaseContext : NetAddress { - napi_async_work work_ = nullptr; - napi_deferred deferred_ = nullptr; - napi_ref callbackRef_ = nullptr; - bool resolved_ = false; - int32_t errorCode_ = 0; - int32_t socketfd_ = -1; - std::string data = ""; - std::string errorString_ = ""; - bool isBound = false; - bool isClose = true; - bool isConnected = false; - bool broadcast = false; - int type = 0; - TCPExtraOptions tcpExtraOptions_; - TCPSocket *tcpSocket_; -}; - -class TCPSocket { -public: - TCPSocket(TcpBaseContext remInfo); - ~TCPSocket(); - - int TcpSocket(int domain, int type, int protocol); - int TcpBind(int fd, const struct sockaddr *addr, socklen_t len); - int TcpConnect(int fd, const struct sockaddr *addr, socklen_t len); - int TcpSend(int fd, const void *buf, size_t len, int flags); - int TcpClose(int fd); - int TcpSetSockopt(int fd, int level, int optname, const void *optval, socklen_t optlen); - void GetJSParameter(napi_env &env, napi_value *parameters, TcpBaseContext *&asyncContext); - void GetSocketInfo(struct sockaddr_in &addr, TcpBaseContext *&asyncContext); - void GetExOpGetJSParameter(napi_env &env, napi_value *parameters, TcpBaseContext *&asyncContext); - TcpBaseContext tcpbaseContext_; -}; -} // namespace NetManagerStandard -} // namespace OHOS -#endif // TCP_SOCKET_H \ No newline at end of file diff --git a/frameworks/js/napi/socket/include/udp_socket.h b/frameworks/js/napi/socket/include/udp_socket.h deleted file mode 100644 index b7cc48a93a29b5c511888ed329606d1ba857c295..0000000000000000000000000000000000000000 --- a/frameworks/js/napi/socket/include/udp_socket.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2021 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 UDP_SOCKET_H -#define UDP_SOCKET_H - -#include "sys/socket.h" -#include "unistd.h" -#include "sys/socket.h" -#include "napi/native_api.h" -#include "napi/native_node_api.h" -#include "netaddress.h" -#include "socket_napi.h" - -#include -#include -#include -#include - -namespace OHOS { -namespace NetManagerStandard { -class UDPSocket; - -struct Baseinfo : NetAddress { - napi_async_work work_ = nullptr; - napi_deferred deferred_ = nullptr; - napi_ref callbackRef_ = nullptr; - bool resolved_ = false; - int32_t errorCode = 0; - int32_t socketfd = -1; - std::string data = ""; - bool isBound = false; - bool isClose = true; - bool isConnected = false; - bool broadcast = false; - int type = 0; - UDPSocket *udpRequestInfo_; -}; - -struct NetState : NetAddress { - bool isBound = false; - bool isClose = false; - bool isConnected = false; -}; - -class UDPSocket { -public: - UDPSocket(Baseinfo remInfo); - ~UDPSocket(); - - int UdpSocket(int domain, int type, int protocol); - int UdpBind(int fd, const struct sockaddr *addr, socklen_t len); - int UdpConnect(int fd, const struct sockaddr *addr, socklen_t len); - int UdpSend(int fd, const void *buf, size_t len, int flags); - int UdpClose(int fd); - void GetJSParameter(napi_env &env, napi_value *parameters, Baseinfo *&asyncContext); - void GetSocketInfo(struct sockaddr_in &addr, Baseinfo *&asyncContext); - - Baseinfo remInfo; -}; -} // namespace NetManagerStandard -} // namespace OHOS -#endif // UDP_SOCKET_H diff --git a/frameworks/js/napi/socket/options/include/extra_options_base.h b/frameworks/js/napi/socket/options/include/extra_options_base.h new file mode 100644 index 0000000000000000000000000000000000000000..9d0c12d3a093743785782a3906f768315e764ebb --- /dev/null +++ b/frameworks/js/napi/socket/options/include/extra_options_base.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2021-2022 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_EXTRA_OPTIONS_BASE_H +#define COMMUNICATIONNETSTACK_EXTRA_OPTIONS_BASE_H + +#include + +namespace OHOS::NetStack { + +class ExtraOptionsBase { +public: + ExtraOptionsBase(); + + ~ExtraOptionsBase() = default; + + void SetReceiveBufferSize(uint32_t receiveBufferSize); + + void SetSendBufferSize(uint32_t sendBufferSize); + + void SetReuseAddress(bool reuseAddress); + + void SetSocketTimeout(uint32_t socketTimeout); + + [[nodiscard]] uint32_t GetReceiveBufferSize() const; + + [[nodiscard]] uint32_t GetSendBufferSize() const; + + [[nodiscard]] bool IsReuseAddress() const; + + [[nodiscard]] uint32_t GetSocketTimeout() const; + +private: + uint32_t receiveBufferSize_; + + uint32_t sendBufferSize_; + + bool reuseAddress_; + + uint32_t socketTimeout_; +}; + +} // namespace OHOS::NetStack + +#endif /* COMMUNICATIONNETSTACK_EXTRA_OPTIONS_BASE_H */ diff --git a/frameworks/js/napi/socket/include/socket_state_base.h b/frameworks/js/napi/socket/options/include/net_address.h similarity index 39% rename from frameworks/js/napi/socket/include/socket_state_base.h rename to frameworks/js/napi/socket/options/include/net_address.h index 005f6f8380f06f598b7fcc3700b054c537898d5b..a1528b599a3e5f0a38b0689cc8f1dd41867b0741 100644 --- a/frameworks/js/napi/socket/include/socket_state_base.h +++ b/frameworks/js/napi/socket/options/include/net_address.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Huawei Device Co., Ltd. + * Copyright (C) 2021-2022 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 @@ -13,54 +13,48 @@ * limitations under the License. */ -#ifndef SOCKET_BASE_CONTEXT_H -#define SOCKET_BASE_CONTEXT_H +#ifndef COMMUNICATIONNETSTACK_NET_ADDRESS_H +#define COMMUNICATIONNETSTACK_NET_ADDRESS_H -#include "napi/native_api.h" -#include "napi/native_node_api.h" -#include "napi_util.h" +#include +#include -namespace OHOS { -namespace NetManagerStandard { -class SocketStateBase { +namespace OHOS::NetStack { + +class NetAddress final { public: - SocketStateBase() {} - ~SocketStateBase() {} - - bool GetBound() - { - return isBound_; - } - - void SetBound(bool bound) - { - this->isBound_ = bound; - } - - bool GetClose() - { - return isClose_; - } - - void SetClose(bool close) - { - this->isClose_ = close; - } - - bool GetConnected() - { - return isConnected_; - } - - void SetConnected(bool connected) - { - this->isConnected_ = connected; - } + enum class Family : uint32_t { + IPv4 = 1, + IPv6 = 2, + }; + + NetAddress(); + + ~NetAddress() = default; + + void SetAddress(const std::string &address); + + void SetFamilyByJsValue(uint32_t family); + + void SetFamilyBySaFamily(sa_family_t family); + + void SetPort(uint16_t port); + + [[nodiscard]] const std::string &GetAddress() const; + + [[nodiscard]] uint32_t GetJsValueFamily() const; + + [[nodiscard]] sa_family_t GetSaFamily() const; + + [[nodiscard]] uint16_t GetPort() const; + private: - bool isBound_ = false; - bool isClose_ = false; - bool isConnected_ = false; + std::string address_; + + Family family_; + + uint16_t port_; }; -} // namespace NetManagerStandard -} // namespace OHOS -#endif // SOCKET_BASE_CONTEXT_H \ No newline at end of file +} // namespace OHOS::NetStack + +#endif /* COMMUNICATIONNETSTACK_NET_ADDRESS_H */ diff --git a/frameworks/js/napi/socket/options/include/socket_remote_info.h b/frameworks/js/napi/socket/options/include/socket_remote_info.h new file mode 100644 index 0000000000000000000000000000000000000000..6d31537db1d4492948f9c3c9d78977d47540f06b --- /dev/null +++ b/frameworks/js/napi/socket/options/include/socket_remote_info.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2021-2022 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_SOCKET_REMOTE_INFO_H +#define COMMUNICATIONNETSTACK_SOCKET_REMOTE_INFO_H + +#include "net_address.h" +#include + +namespace OHOS::NetStack { + +class SocketRemoteInfo final { + +public: + SocketRemoteInfo(); + + ~SocketRemoteInfo() = default; + + void SetAddress(const std::string &address); + + void SetFamily(sa_family_t family); + + void SetPort(uint16_t port); + + void SetSize(uint32_t size); + + [[nodiscard]] const std::string &GetAddress() const; + + [[nodiscard]] const std::string &GetFamily() const; + + [[nodiscard]] uint16_t GetPort() const; + + [[nodiscard]] uint32_t GetSize() const; + +private: + std::string address_; + + std::string family_; + + uint16_t port_; + + uint32_t size_; +}; + +} // namespace OHOS::NetStack + +#endif /* COMMUNICATIONNETSTACK_SOCKET_REMOTE_INFO_H */ diff --git a/frameworks/js/napi/http/include/http_base_context.h b/frameworks/js/napi/socket/options/include/socket_state_base.h similarity index 46% rename from frameworks/js/napi/http/include/http_base_context.h rename to frameworks/js/napi/socket/options/include/socket_state_base.h index a3f45f9cc8021163cb5458b5a87d8ebefac09020..aa837e822f2553d5d31a37a7d2f487c585ab6b45 100644 --- a/frameworks/js/napi/http/include/http_base_context.h +++ b/frameworks/js/napi/socket/options/include/socket_state_base.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Huawei Device Co., Ltd. + * Copyright (C) 2021-2022 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 @@ -13,29 +13,37 @@ * limitations under the License. */ -#ifndef HTTP_BASE_CONTEXT_H -#define HTTP_BASE_CONTEXT_H +#ifndef COMMUNICATIONNETSTACK_SOCKET_STATE_BASE_H +#define COMMUNICATIONNETSTACK_SOCKET_STATE_BASE_H -#include "napi/native_api.h" -#include "napi/native_node_api.h" -#include "napi_util.h" +namespace OHOS::NetStack { -namespace OHOS { -namespace NetManagerStandard { -class HttpBaseContext { +class SocketStateBase final { public: - napi_async_work work_ = nullptr; - napi_deferred deferred_ = nullptr; - napi_ref callbackRef_ = nullptr; - int32_t errorCode_ = ERROR_DEFAULT; - bool resolved_ = false; - napi_value result_ = 0; - bool isCallback_ = false; + SocketStateBase(); -public: - HttpBaseContext() {} - ~HttpBaseContext() {} + ~SocketStateBase() = default; + + void SetIsBound(bool isBound); + + void SetIsClose(bool isClose); + + void SetIsConnected(bool isConnected); + + [[nodiscard]] bool IsBound() const; + + [[nodiscard]] bool IsClose() const; + + [[nodiscard]] bool IsConnected() const; + +private: + bool isBound_; + + bool isClose_; + + bool isConnected_; }; -} // namespace NetManagerStandard -} // namespace OHOS -#endif // HTTP_BASE_CONTEXT_H \ No newline at end of file + +} // namespace OHOS::NetStack + +#endif /* COMMUNICATIONNETSTACK_SOCKET_STATE_BASE_H */ diff --git a/frameworks/js/napi/socket/options/include/tcp_connect_options.h b/frameworks/js/napi/socket/options/include/tcp_connect_options.h new file mode 100644 index 0000000000000000000000000000000000000000..7f4f3bedda9a05ae08ed13b7335ebc1348b0fafd --- /dev/null +++ b/frameworks/js/napi/socket/options/include/tcp_connect_options.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2021-2022 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_TCP_CONNECT_OPTIONS_H +#define COMMUNICATIONNETSTACK_TCP_CONNECT_OPTIONS_H + +#include "net_address.h" + +#define DEFAULT_CONNECT_TIMEOUT 5 // 5 Seconds + +namespace OHOS::NetStack { + +class TcpConnectOptions final { + +public: + TcpConnectOptions(); + + ~TcpConnectOptions() = default; + + void SetTimeout(uint32_t timeout); + + [[nodiscard]] uint32_t GetTimeout() const; + + NetAddress address; + +private: + uint32_t timeout_; +}; + +} // namespace OHOS::NetStack + +#endif /* COMMUNICATIONNETSTACK_TCP_CONNECT_OPTIONS_H */ diff --git a/frameworks/js/napi/socket/options/include/tcp_extra_options.h b/frameworks/js/napi/socket/options/include/tcp_extra_options.h new file mode 100644 index 0000000000000000000000000000000000000000..ef505588d36f06cf9ae90195a29fe3f73c8e0e9f --- /dev/null +++ b/frameworks/js/napi/socket/options/include/tcp_extra_options.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2021-2022 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_TCP_EXTRA_OPTIONS_H +#define COMMUNICATIONNETSTACK_TCP_EXTRA_OPTIONS_H + +#include "extra_options_base.h" + +namespace OHOS::NetStack { + +class TCPExtraOptions final : public ExtraOptionsBase { + +private: + class SocketLinger { + public: + SocketLinger(); + + ~SocketLinger() = default; + + void SetOn(bool on); + + void SetLinger(uint32_t linger); + + [[nodiscard]] bool IsOn() const; + + [[nodiscard]] uint32_t GetLinger() const; + + private: + bool on_; + uint32_t linger_; + }; + +public: + TCPExtraOptions(); + + ~TCPExtraOptions() = default; + + void SetKeepAlive(bool keepAlive); + + void SetOOBInline(bool OOBInline); + + void SetTCPNoDelay(bool TCPNoDelay); + + [[nodiscard]] bool IsKeepAlive() const; + + [[nodiscard]] bool IsOOBInline() const; + + [[nodiscard]] bool IsTCPNoDelay() const; + + SocketLinger socketLinger; + +private: + bool keepAlive_; + + bool OOBInline_; + + bool TCPNoDelay_; +}; + +} // namespace OHOS::NetStack + +#endif /* COMMUNICATIONNETSTACK_TCP_EXTRA_OPTIONS_H */ diff --git a/frameworks/js/napi/socket/options/include/tcp_send_options.h b/frameworks/js/napi/socket/options/include/tcp_send_options.h new file mode 100644 index 0000000000000000000000000000000000000000..48bdafb05a22ff70827b807a2ea59ea9aa8ea15a --- /dev/null +++ b/frameworks/js/napi/socket/options/include/tcp_send_options.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2021-2022 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_TCP_SEND_OPTIONS_H +#define COMMUNICATIONNETSTACK_TCP_SEND_OPTIONS_H + +#include + +namespace OHOS::NetStack { + +class TCPSendOptions final { + +public: + TCPSendOptions() = default; + + ~TCPSendOptions() = default; + + void SetData(const std::string &data); + + void SetData(void *data, size_t size); + + void SetEncoding(const std::string &encoding); + + [[nodiscard]] const std::string &GetData() const; + + [[nodiscard]] const std::string &GetEncoding() const; + +private: + std::string data_; + + std::string encoding_; +}; + +} // namespace OHOS::NetStack + +#endif /* COMMUNICATIONNETSTACK_TCP_SEND_OPTIONS_H */ diff --git a/frameworks/js/napi/socket/include/udp_extra_options.h b/frameworks/js/napi/socket/options/include/udp_extra_options.h similarity index 54% rename from frameworks/js/napi/socket/include/udp_extra_options.h rename to frameworks/js/napi/socket/options/include/udp_extra_options.h index 49b29f223af3d6baa9f7b076f9363cdea9ff0479..15ecb36ebdc524c5f92f0a351e04fb884c058170 100644 --- a/frameworks/js/napi/socket/include/udp_extra_options.h +++ b/frameworks/js/napi/socket/options/include/udp_extra_options.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Huawei Device Co., Ltd. + * Copyright (C) 2021-2022 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 @@ -13,30 +13,28 @@ * limitations under the License. */ -#ifndef UDP_EXTRA_OPTIONS_H -#define UDP_EXTRA_OPTIONS_H +#ifndef COMMUNICATIONNETSTACK_UDP_EXTRA_OPTIONS_H +#define COMMUNICATIONNETSTACK_UDP_EXTRA_OPTIONS_H #include "extra_options_base.h" -namespace OHOS { -namespace NetManagerStandard { -class UDPExtraOptions : public ExtraOptionsBase { +namespace OHOS::NetStack { + +class UDPExtraOptions final : public ExtraOptionsBase { + public: - UDPExtraOptions () {} - ~UDPExtraOptions() {} - - bool GetBroadcast() - { - return broadcast_; - } - - void SetBroadcast(bool broadcast) - { - this->broadcast_ = broadcast; - } + UDPExtraOptions(); + + ~UDPExtraOptions() = default; + + void SetBroadcast(bool broadcast); + + [[nodiscard]] bool IsBroadcast() const; + private: - bool broadcast_ = false; + bool broadcast_; }; -} // namespace NetManagerStandard -} // namespace OHOS -#endif // UDP_EXTRA_OPTIONS_H \ No newline at end of file + +} // namespace OHOS::NetStack + +#endif /* COMMUNICATIONNETSTACK_UDP_EXTRA_OPTIONS_H */ diff --git a/frameworks/js/napi/socket/options/include/udp_send_options.h b/frameworks/js/napi/socket/options/include/udp_send_options.h new file mode 100644 index 0000000000000000000000000000000000000000..d866c45c25c3cf1b0c563a5e4bbcd667c1edce02 --- /dev/null +++ b/frameworks/js/napi/socket/options/include/udp_send_options.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2021-2022 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_UDP_SEND_OPTIONS_H +#define COMMUNICATIONNETSTACK_UDP_SEND_OPTIONS_H + +#include "net_address.h" + +namespace OHOS::NetStack { + +class UDPSendOptions final { + +public: + UDPSendOptions() = default; + + ~UDPSendOptions() = default; + + void SetData(const std::string &data); + + void SetData(void *data, size_t size); + + [[nodiscard]] const std::string &GetData() const; + + NetAddress address; + +private: + std::string data_; +}; + +} // namespace OHOS::NetStack + +#endif /* COMMUNICATIONNETSTACK_UDP_SEND_OPTIONS_H */ diff --git a/frameworks/js/napi/socket/options/src/extra_options_base.cpp b/frameworks/js/napi/socket/options/src/extra_options_base.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2869ae1711740030ce289d22a465cf4721ff66e4 --- /dev/null +++ b/frameworks/js/napi/socket/options/src/extra_options_base.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2021-2022 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 "extra_options_base.h" + +namespace OHOS::NetStack { + +ExtraOptionsBase::ExtraOptionsBase() + : receiveBufferSize_(0), sendBufferSize_(0), reuseAddress_(false), socketTimeout_(0) +{ +} + +void ExtraOptionsBase::SetReceiveBufferSize(uint32_t receiveBufferSize) +{ + receiveBufferSize_ = receiveBufferSize; +} + +void ExtraOptionsBase::SetSendBufferSize(uint32_t sendBufferSize) +{ + sendBufferSize_ = sendBufferSize; +} + +void ExtraOptionsBase::SetReuseAddress(bool reuseAddress) +{ + reuseAddress_ = reuseAddress; +} + +void ExtraOptionsBase::SetSocketTimeout(uint32_t socketTimeout) +{ + socketTimeout_ = socketTimeout; +} + +uint32_t ExtraOptionsBase::GetReceiveBufferSize() const +{ + return receiveBufferSize_; +} + +uint32_t ExtraOptionsBase::GetSendBufferSize() const +{ + return sendBufferSize_; +} + +bool ExtraOptionsBase::IsReuseAddress() const +{ + return reuseAddress_; +} + +uint32_t ExtraOptionsBase::GetSocketTimeout() const +{ + return socketTimeout_; +} + +} // namespace OHOS::NetStack diff --git a/utils/log/src/netmgr_log_wrapper.cpp b/frameworks/js/napi/socket/options/src/net_address.cpp similarity index 38% rename from utils/log/src/netmgr_log_wrapper.cpp rename to frameworks/js/napi/socket/options/src/net_address.cpp index 7c681f77fc6e2072ff1f9c8482e01693d6ca8897..f9c2f72c4848f7a40dd292fe186df171829bab69 100644 --- a/utils/log/src/netmgr_log_wrapper.cpp +++ b/frameworks/js/napi/socket/options/src/net_address.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (C) 2021-2022 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 @@ -13,35 +13,57 @@ * limitations under the License. */ -#include "netmgr_log_wrapper.h" +#include "net_address.h" -namespace OHOS { -namespace NetManagerStandard { -// initial static member object -NetMgrLogLevel NetMgrLogWrapper::level_ = NetMgrLogLevel::DEBUG; +namespace OHOS::NetStack { -bool NetMgrLogWrapper::JudgeLevel(const NetMgrLogLevel &level) +NetAddress::NetAddress() : family_(Family::IPv4), port_(0) {} + +void NetAddress::SetAddress(const std::string &address) { - const NetMgrLogLevel &curLevel = NetMgrLogWrapper::GetLogLevel(); - if (level < curLevel) { - return false; + address_ = address; +} + +void NetAddress::SetFamilyByJsValue(uint32_t family) +{ + if (static_cast(family) == Family::IPv6) { + family_ = Family::IPv6; } - return true; } -std::string NetMgrLogWrapper::GetBriefFileName(const std::string &file) +void NetAddress::SetFamilyBySaFamily(sa_family_t family) { - auto pos = file.find_last_of("/"); - if (pos != std::string::npos) { - return file.substr(pos + 1); + if (family == AF_INET6) { + family_ = Family::IPv6; } +} + +void NetAddress::SetPort(uint16_t port) +{ + port_ = port; +} + +const std::string &NetAddress::GetAddress() const +{ + return address_; +} - pos = file.find_last_of("\\"); - if (pos != std::string::npos) { - return file.substr(pos + 1); +sa_family_t NetAddress::GetSaFamily() const +{ + if (family_ == Family::IPv6) { + return AF_INET6; } + return AF_INET; +} - return file; +uint32_t NetAddress::GetJsValueFamily() const +{ + return static_cast(family_); } -} // namespace NetManagerStandard -} // namespace OHOS \ No newline at end of file + +uint16_t NetAddress::GetPort() const +{ + return port_; +} + +} // namespace OHOS::NetStack diff --git a/frameworks/js/napi/socket/options/src/socket_remote_info.cpp b/frameworks/js/napi/socket/options/src/socket_remote_info.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3da7c2fb038362b08e358f410bc793540029fcf2 --- /dev/null +++ b/frameworks/js/napi/socket/options/src/socket_remote_info.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2021-2022 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 "socket_remote_info.h" + +#include + +#define FAMILY(family) #family + +namespace OHOS::NetStack { + +SocketRemoteInfo::SocketRemoteInfo() : port_(0), size_(0) {} + +void SocketRemoteInfo::SetAddress(const std::string &address) +{ + address_ = address; +} + +void SocketRemoteInfo::SetFamily(sa_family_t family) +{ + if (family == AF_INET) { + family_ = FAMILY(IPv4); + } else if (family == AF_INET6) { + family_ = FAMILY(IPv6); + } else { + family_ = FAMILY(Others); + } +} + +void SocketRemoteInfo::SetPort(uint16_t port) +{ + port_ = port; +} + +void SocketRemoteInfo::SetSize(uint32_t size) +{ + size_ = size; +} + +const std::string &SocketRemoteInfo::GetAddress() const +{ + return address_; +} + +const std::string &SocketRemoteInfo::GetFamily() const +{ + return family_; +} + +uint16_t SocketRemoteInfo::GetPort() const +{ + return port_; +} + +uint32_t SocketRemoteInfo::GetSize() const +{ + return size_; +} + +} // namespace OHOS::NetStack \ No newline at end of file diff --git a/frameworks/js/napi/socket/options/src/socket_state_base.cpp b/frameworks/js/napi/socket/options/src/socket_state_base.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ae86a6060b1edba2134131c52e38825ec7b8c047 --- /dev/null +++ b/frameworks/js/napi/socket/options/src/socket_state_base.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2021-2022 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 "socket_state_base.h" + +namespace OHOS::NetStack { + +SocketStateBase::SocketStateBase() : isBound_(false), isClose_(false), isConnected_(false) {} + +void SocketStateBase::SetIsBound(bool isBound) +{ + isBound_ = isBound; +} + +void SocketStateBase::SetIsClose(bool isClose) +{ + isClose_ = isClose; +} + +void SocketStateBase::SetIsConnected(bool isConnected) +{ + isConnected_ = isConnected; +} + +bool SocketStateBase::IsBound() const +{ + return isBound_; +} + +bool SocketStateBase::IsClose() const +{ + return isClose_; +} + +bool SocketStateBase::IsConnected() const +{ + return isConnected_; +} + +} // namespace OHOS::NetStack diff --git a/frameworks/js/napi/http/include/http_event_list.h b/frameworks/js/napi/socket/options/src/tcp_connect_options.cpp similarity index 55% rename from frameworks/js/napi/http/include/http_event_list.h rename to frameworks/js/napi/socket/options/src/tcp_connect_options.cpp index 7fb5647f696ed76b6444b96f728fc9bdcde681f9..1dce83fd54ce51b20574a1da951bd5ad197db122 100644 --- a/frameworks/js/napi/http/include/http_event_list.h +++ b/frameworks/js/napi/socket/options/src/tcp_connect_options.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Huawei Device Co., Ltd. + * Copyright (C) 2021-2022 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 @@ -13,22 +13,20 @@ * limitations under the License. */ -#ifndef HTTP_EVENT_LIST_H -#define HTTP_EVENT_LIST_H +#include "tcp_connect_options.h" -#include "napi/native_api.h" -#include "napi/native_node_api.h" +namespace OHOS::NetStack { -namespace OHOS { -namespace NetManagerStandard { -class HttpRequest; -struct EventListener { - napi_env env_; - int32_t eventType_; - bool isOnce_; - napi_ref callbackRef_; - HttpRequest *httpRequestInfo_; -}; -} // namespace NetManagerStandard -} // namespace OHOS -#endif // HTTP_EVENT_LIST_H \ No newline at end of file +TcpConnectOptions::TcpConnectOptions() : timeout_(DEFAULT_CONNECT_TIMEOUT) {} + +void TcpConnectOptions::SetTimeout(uint32_t timeout) +{ + timeout_ = timeout; +} + +uint32_t TcpConnectOptions::GetTimeout() const +{ + return timeout_; +} + +} // namespace OHOS::NetStack \ No newline at end of file diff --git a/frameworks/js/napi/socket/options/src/tcp_extra_options.cpp b/frameworks/js/napi/socket/options/src/tcp_extra_options.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ee790740abc247189432f0ce7c4e1a595b835d93 --- /dev/null +++ b/frameworks/js/napi/socket/options/src/tcp_extra_options.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2021-2022 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 "tcp_extra_options.h" + +namespace OHOS::NetStack { + +TCPExtraOptions::SocketLinger::SocketLinger() : on_(false), linger_(0) {} + +void TCPExtraOptions::SocketLinger::SetOn(bool on) +{ + on_ = on; +} + +void TCPExtraOptions::SocketLinger::SetLinger(uint32_t linger) +{ + linger_ = linger; +} + +bool TCPExtraOptions::SocketLinger::IsOn() const +{ + return on_; +} + +uint32_t TCPExtraOptions::SocketLinger::GetLinger() const +{ + return linger_; +} + +TCPExtraOptions::TCPExtraOptions() : keepAlive_(false), OOBInline_(false), TCPNoDelay_(false) {} + +void TCPExtraOptions::SetKeepAlive(bool keepAlive) +{ + keepAlive_ = keepAlive; +} + +void TCPExtraOptions::SetOOBInline(bool OOBInline) +{ + OOBInline_ = OOBInline; +} + +void TCPExtraOptions::SetTCPNoDelay(bool TCPNoDelay) +{ + TCPNoDelay_ = TCPNoDelay; +} + +bool TCPExtraOptions::IsKeepAlive() const +{ + return keepAlive_; +} + +bool TCPExtraOptions::IsOOBInline() const +{ + return OOBInline_; +} + +bool TCPExtraOptions::IsTCPNoDelay() const +{ + return TCPNoDelay_; +} + +} // namespace OHOS::NetStack \ No newline at end of file diff --git a/frameworks/js/napi/socket/options/src/tcp_send_options.cpp b/frameworks/js/napi/socket/options/src/tcp_send_options.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9967827572385d10100486acf71c80f417c5aa4e --- /dev/null +++ b/frameworks/js/napi/socket/options/src/tcp_send_options.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2021-2022 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 "tcp_send_options.h" + +namespace OHOS::NetStack { + +void TCPSendOptions::SetData(const std::string &data) +{ + data_ = data; +} + +void TCPSendOptions::SetData(void *data, size_t size) +{ + data_.append(static_cast(data), size); +} + +void TCPSendOptions::SetEncoding(const std::string &encoding) +{ + encoding_ = encoding; +} + +const std::string &TCPSendOptions::GetData() const +{ + return data_; +} + +const std::string &TCPSendOptions::GetEncoding() const +{ + return encoding_; +} + +} // namespace OHOS::NetStack \ No newline at end of file diff --git a/frameworks/js/napi/socket/options/src/udp_extra_options.cpp b/frameworks/js/napi/socket/options/src/udp_extra_options.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bbabcd57000650bc86cf74dc79e1d6094df1893a --- /dev/null +++ b/frameworks/js/napi/socket/options/src/udp_extra_options.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2021-2022 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 "udp_extra_options.h" + +namespace OHOS::NetStack { + +UDPExtraOptions::UDPExtraOptions() : broadcast_(false) {} + +void UDPExtraOptions::SetBroadcast(bool broadcast) +{ + broadcast_ = broadcast; +} + +bool UDPExtraOptions::IsBroadcast() const +{ + return broadcast_; +} + +} // namespace OHOS::NetStack \ No newline at end of file diff --git a/frameworks/js/napi/socket/options/src/udp_send_options.cpp b/frameworks/js/napi/socket/options/src/udp_send_options.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1e18938cdbdd0b261b563cb2d1d381e5a9d550d2 --- /dev/null +++ b/frameworks/js/napi/socket/options/src/udp_send_options.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2021-2022 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 "udp_send_options.h" + +namespace OHOS::NetStack { + +void UDPSendOptions::SetData(const std::string &data) +{ + data_ = data; +} + +void UDPSendOptions::SetData(void *data, size_t size) +{ + data_.append(static_cast(data), size); +} + +const std::string &UDPSendOptions::GetData() const +{ + return data_; +} + +} // namespace OHOS::NetStack \ No newline at end of file diff --git a/frameworks/js/napi/socket/socket_exec/include/socket_exec.h b/frameworks/js/napi/socket/socket_exec/include/socket_exec.h new file mode 100644 index 0000000000000000000000000000000000000000..dc4bde4d30fc3a8510b5f6702ca63eb9c4a33a1b --- /dev/null +++ b/frameworks/js/napi/socket/socket_exec/include/socket_exec.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2021-2022 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_SOCKET_EXEC_H +#define COMMUNICATIONNETSTACK_SOCKET_EXEC_H + +#include "bind_context.h" +#include "common_context.h" +#include "connect_context.h" +#include "tcp_extra_context.h" +#include "tcp_send_context.h" +#include "udp_extra_context.h" +#include "udp_send_context.h" + +namespace OHOS::NetStack::SocketExec { + +int MakeTcpSocket(sa_family_t family); + +int MakeUdpSocket(sa_family_t family); + +/* async work execute */ +bool ExecBind(BindContext *context); + +bool ExecUdpSend(UdpSendContext *context); + +bool ExecConnect(ConnectContext *context); + +bool ExecTcpSend(TcpSendContext *context); + +bool ExecClose(CloseContext *context); + +bool ExecGetState(GetStateContext *context); + +bool ExecGetRemoteAddress(GetRemoteAddressContext *context); + +bool ExecTcpSetExtraOptions(TcpSetExtraOptionsContext *context); + +bool ExecUdpSetExtraOptions(UdpSetExtraOptionsContext *context); + +/* async work callback */ +napi_value BindCallback(BindContext *context); + +napi_value UdpSendCallback(UdpSendContext *context); + +napi_value ConnectCallback(ConnectContext *context); + +napi_value TcpSendCallback(TcpSendContext *context); + +napi_value CloseCallback(CloseContext *context); + +napi_value GetStateCallback(GetStateContext *context); + +napi_value GetRemoteAddressCallback(GetRemoteAddressContext *context); + +napi_value TcpSetExtraOptionsCallback(TcpSetExtraOptionsContext *context); + +napi_value UdpSetExtraOptionsCallback(UdpSetExtraOptionsContext *context); + +} // namespace OHOS::NetStack::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 new file mode 100644 index 0000000000000000000000000000000000000000..446746d879f3203583b8e2f545709be34cad4c69 --- /dev/null +++ b/frameworks/js/napi/socket/socket_exec/src/socket_exec.cpp @@ -0,0 +1,873 @@ +/* + * Copyright (C) 2021-2022 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 "socket_exec.h" + +#include "context_key.h" +#include "event_list.h" +#include "netstack_log.h" +#include "netstack_napi_utils.h" +#include "securec.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEFAULT_BUFFER_SIZE 8192 + +#define DEFAULT_POLL_TIMEOUT 500 // 0.5 Seconds + +#define ADDRESS_INVALID -1 + +namespace OHOS::NetStack::SocketExec { + +static void EmitError(BaseContext *context, int32_t errorNum) +{ + napi_value error = NapiUtils::CreateObject(context->GetEnv()); + NapiUtils::SetInt32Property(context->GetEnv(), error, KEY_ERROR_CODE, errorNum); + context->Emit(EVENT_ERROR, std::make_pair(NapiUtils::GetUndefined(context->GetEnv()), error)); +} + +static std::string MakeAddressString(sockaddr *addr) +{ + if (addr->sa_family == AF_INET) { + auto *addr4 = (sockaddr_in *)addr; + const char *str = inet_ntoa(addr4->sin_addr); + if (str == nullptr || strlen(str) == 0) { + return {}; + } + return str; + } else if (addr->sa_family == AF_INET6) { + auto *addr6 = (sockaddr_in6 *)addr; + char str[INET6_ADDRSTRLEN] = {0}; + if (inet_ntop(AF_INET6, &addr6->sin6_addr, str, INET6_ADDRSTRLEN) == nullptr || strlen(str) == 0) { + return {}; + } + return str; + } + return {}; +} + +static napi_value MakeJsMessageParam(napi_env env, napi_value msgBuffer, SocketRemoteInfo *remoteInfo) +{ + napi_value obj = NapiUtils::CreateObject(env); + if (NapiUtils::GetValueType(env, obj) != napi_object) { + return nullptr; + } + NapiUtils::SetNamedProperty(env, obj, KEY_MESSAGE, msgBuffer); + napi_value jsRemoteInfo = NapiUtils::CreateObject(env); + if (NapiUtils::GetValueType(env, jsRemoteInfo) != napi_object) { + return nullptr; + } + NapiUtils::SetStringPropertyUtf8(env, jsRemoteInfo, KEY_ADDRESS, remoteInfo->GetAddress()); + NapiUtils::SetStringPropertyUtf8(env, jsRemoteInfo, KEY_FAMILY, remoteInfo->GetFamily()); + NapiUtils::SetUint32Property(env, jsRemoteInfo, KEY_PORT, remoteInfo->GetPort()); + NapiUtils::SetUint32Property(env, jsRemoteInfo, KEY_SIZE, remoteInfo->GetSize()); + + NapiUtils::SetNamedProperty(env, obj, KEY_REMOTE_INFO, jsRemoteInfo); + return obj; +} + +static void OnRecvMessage(BaseContext *context, void *data, size_t len, sockaddr *addr) +{ + if (data == nullptr || len <= 0) { + return; + } + + void *dataHandle = nullptr; + napi_value msgBuffer = NapiUtils::CreateArrayBuffer(context->GetEnv(), len, &dataHandle); + if (dataHandle != nullptr) { + (void)memcpy_s(dataHandle, len, data, len); + + SocketRemoteInfo remoteInfo; + std::string address = MakeAddressString(addr); + if (address.empty()) { + EmitError(context, ADDRESS_INVALID); + return; + } + remoteInfo.SetAddress(address); + remoteInfo.SetFamily(addr->sa_family); + if (addr->sa_family == AF_INET) { + auto *addr4 = (sockaddr_in *)addr; + remoteInfo.SetPort(ntohs(addr4->sin_port)); + } else if (addr->sa_family == AF_INET6) { + auto *addr6 = (sockaddr_in6 *)addr; + remoteInfo.SetPort(ntohs(addr6->sin6_port)); + } + remoteInfo.SetSize(len); + + napi_value undefined = NapiUtils::GetUndefined(context->GetEnv()); + napi_value obj = MakeJsMessageParam(context->GetEnv(), msgBuffer, &remoteInfo); + + if (NapiUtils::GetValueType(context->GetEnv(), obj) != napi_object) { + return; + } + context->Emit(EVENT_MESSAGE, std::make_pair(undefined, obj)); + } +} + +class MessageCallback { +public: + MessageCallback() = delete; + + ~MessageCallback() = default; + + explicit MessageCallback(BaseContext *context) : context_(context) {} + + virtual void operator()(int sock, void *data, size_t dataLen, sockaddr *addr) const = 0; + +protected: + BaseContext *context_; +}; + +class TcpMessageCallback final : public MessageCallback { +public: + TcpMessageCallback() = delete; + + ~TcpMessageCallback() = default; + + explicit TcpMessageCallback(BaseContext *context) : MessageCallback(context) {} + + void operator()(int sock, void *data, size_t dataLen, sockaddr *addr) const override + { + (void)addr; + + sa_family_t family; + socklen_t len = sizeof(family); + int ret = getsockname(sock, (sockaddr *)&family, &len); + if (ret < 0) { + return; + } + + if (family == AF_INET) { + sockaddr_in addr4 = {0}; + socklen_t len4 = sizeof(sockaddr_in); + + ret = getpeername(sock, (sockaddr *)&addr4, &len4); + if (ret < 0) { + return; + } + OnRecvMessage(context_, data, dataLen, (sockaddr *)&addr4); + return; + } else if (family == AF_INET6) { + sockaddr_in6 addr6 = {0}; + socklen_t len6 = sizeof(sockaddr_in6); + + ret = getpeername(sock, (sockaddr *)&addr6, &len6); + if (ret < 0) { + return; + } + OnRecvMessage(context_, data, dataLen, (sockaddr *)&addr6); + return; + } + } +}; + +class UdpMessageCallback final : public MessageCallback { +public: + UdpMessageCallback() = delete; + + ~UdpMessageCallback() = default; + + explicit UdpMessageCallback(BaseContext *context) : MessageCallback(context) {} + + void operator()(int sock, void *data, size_t dataLen, sockaddr *addr) const override + { + OnRecvMessage(context_, data, dataLen, addr); + } +}; + +static bool MakeNonBlock(int sock) +{ + int flags = fcntl(sock, F_GETFL, 0); + while (flags == -1 && errno == EINTR) { + flags = fcntl(sock, F_GETFL, 0); + } + if (flags == -1) { + NETSTACK_LOGE("make non block failed %{public}s", strerror(errno)); + return false; + } + int ret = fcntl(sock, F_SETFL, flags | O_NONBLOCK); + while (ret == -1 && errno == EINTR) { + ret = fcntl(sock, F_SETFL, flags | O_NONBLOCK); + } + if (ret == -1) { + NETSTACK_LOGE("make non block failed %{public}s", strerror(errno)); + return false; + } + return true; +} + +static bool PollSendData(int sock, const char *data, size_t size, sockaddr *addr, socklen_t addrLen) +{ + int bufferSize = DEFAULT_BUFFER_SIZE; + int opt = 0; + socklen_t optLen = sizeof(opt); + if (getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void *)&opt, &optLen) >= 0 && opt > 0) { + bufferSize = opt; + } + int sockType = 0; + optLen = sizeof(sockType); + if (getsockopt(sock, SOL_SOCKET, SO_TYPE, (void *)&sockType, &optLen) < 0) { + NETSTACK_LOGI("get sock opt sock type failed = %{public}s", strerror(errno)); + return false; + } + + auto curPos = data; + auto leftSize = size; + nfds_t num = 1; + pollfd fds[1] = {{0}}; + fds[0].fd = sock; + fds[0].events = 0; + fds[0].events |= POLLOUT; + + while (leftSize > 0) { + int ret = poll(fds, num, DEFAULT_POLL_TIMEOUT); + if (ret == -1) { + NETSTACK_LOGE("poll to send failed %{public}s", strerror(errno)); + return false; + } + if (ret == 0) { + NETSTACK_LOGE("poll to send timeout"); + return false; + } + + size_t sendSize = leftSize; + if (sockType != SOCK_STREAM) { + sendSize = std::min(leftSize, bufferSize); + } + auto sendLen = sendto(sock, curPos, sendSize, 0, addr, addrLen); + if (sendLen < 0) { + if (errno == EAGAIN) { + continue; + } + NETSTACK_LOGE("send failed %{public}s", strerror(errno)); + return false; + } + if (sendLen == 0) { + break; + } + curPos += sendLen; + leftSize -= sendLen; + } + + if (leftSize != 0) { + NETSTACK_LOGE("send not complete"); + return false; + } + return true; +} + +static bool PollRecvData(int sock, sockaddr *addr, socklen_t addrLen, const MessageCallback &callback) +{ + int bufferSize = DEFAULT_BUFFER_SIZE; + int opt = 0; + socklen_t optLen = sizeof(opt); + if (getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void *)&opt, &optLen) >= 0 && opt > 0) { + bufferSize = opt; + } + + auto deleter = [](const char *s) { free((void *)s); }; + std::unique_ptr buf((char *)malloc(bufferSize), deleter); + + nfds_t num = 1; + pollfd fds[1] = {{0}}; + fds[0].fd = sock; + fds[0].events = 0; + fds[0].events |= POLLIN; + + while (true) { + int ret = poll(fds, num, DEFAULT_POLL_TIMEOUT); + if (ret == -1) { + NETSTACK_LOGE("poll to recv failed %{public}s", strerror(errno)); + return false; + } + if (ret == 0) { + break; + } + (void)memset_s(buf.get(), bufferSize, 0, bufferSize); + socklen_t tempAddrLen = addrLen; + auto recvLen = recvfrom(sock, buf.get(), bufferSize, 0, addr, &tempAddrLen); + if (recvLen < 0) { + if (errno == EAGAIN) { + continue; + } + NETSTACK_LOGE("recv failed %{public}s", strerror(errno)); + return false; + } + if (recvLen == 0) { + break; + } + callback(sock, buf.get(), recvLen, addr); + } + + return true; +} + +static bool NonBlockConnect(int sock, sockaddr *addr, socklen_t addrLen, uint32_t timeoutSec) +{ + int ret = connect(sock, addr, addrLen); + if (ret >= 0) { + return true; + } + if (errno != EINPROGRESS) { + return false; + } + + fd_set set = {0}; + FD_ZERO(&set); + FD_SET(sock, &set); + if (timeoutSec == 0) { + timeoutSec = DEFAULT_CONNECT_TIMEOUT; + } + timeval timeout = { + .tv_sec = timeoutSec, + .tv_usec = 0, + }; + + ret = select(sock + 1, nullptr, &set, nullptr, &timeout); + if (ret < 0) { + NETSTACK_LOGE("select error: %{public}s\n", strerror(errno)); + return false; + } else if (ret == 0) { + NETSTACK_LOGE("timeout!"); + return false; + } + + int err = 0; + socklen_t optLen = sizeof(err); + ret = getsockopt(sock, SOL_SOCKET, SO_ERROR, (void *)&err, &optLen); + if (ret < 0) { + return false; + } + if (err != 0) { + return false; + } + return true; +} + +static void GetAddr(NetAddress *address, sockaddr_in *addr4, sockaddr_in6 *addr6, sockaddr **addr, socklen_t *len) +{ + sa_family_t family = address->GetSaFamily(); + if (family == AF_INET) { + addr4->sin_family = AF_INET; + addr4->sin_port = htons(address->GetPort()); + addr4->sin_addr.s_addr = inet_addr(address->GetAddress().c_str()); + *addr = (sockaddr *)addr4; + *len = sizeof(sockaddr_in); + } else if (family == AF_INET6) { + addr6->sin6_family = AF_INET6; + addr6->sin6_port = htons(address->GetPort()); + inet_pton(AF_INET6, address->GetAddress().c_str(), &addr6->sin6_addr); + *addr = (sockaddr *)addr6; + *len = sizeof(sockaddr_in6); + } +} + +static bool SetBaseOptions(int sock, ExtraOptionsBase *option) +{ + if (option->GetReceiveBufferSize() != 0) { + int size = (int)option->GetReceiveBufferSize(); + if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void *)&size, sizeof(size)) < 0) { + return false; + } + } + + if (option->GetSendBufferSize() != 0) { + int size = (int)option->GetSendBufferSize(); + if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void *)&size, sizeof(size)) < 0) { + return false; + } + } + + if (option->IsReuseAddress()) { + int reuse = 1; + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&reuse, sizeof(reuse)) < 0) { + return false; + } + } + + if (option->GetSocketTimeout() != 0) { + timeval timeout = {(int)option->GetSocketTimeout(), 0}; + if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (void *)&timeout, sizeof(timeout)) < 0) { + return false; + } + if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (void *)&timeout, sizeof(timeout)) < 0) { + return false; + } + } + + return true; +} + +int MakeTcpSocket(sa_family_t family) +{ + if (family != AF_INET && family != AF_INET6) { + return -1; + } + int sock = socket(family, SOCK_STREAM, IPPROTO_TCP); + if (sock < 0) { + return -1; + } + if (!MakeNonBlock(sock)) { + close(sock); + return -1; + } + return sock; +} + +int MakeUdpSocket(sa_family_t family) +{ + if (family != AF_INET && family != AF_INET6) { + return -1; + } + int sock = socket(family, SOCK_DGRAM, IPPROTO_UDP); + if (sock < 0) { + return -1; + } + if (!MakeNonBlock(sock)) { + close(sock); + return -1; + } + return sock; +} + +bool ExecBind(BindContext *context) +{ + sockaddr_in addr4 = {0}; + sockaddr_in6 addr6 = {0}; + sockaddr *addr = nullptr; + socklen_t len; + GetAddr(&context->address, &addr4, &addr6, &addr, &len); + if (addr == nullptr) { + NETSTACK_LOGE("addr family error"); + context->SetErrorCode(ADDRESS_INVALID); + return false; + } + + if (bind(context->GetSocketFd(), (const sockaddr *)addr, len) < 0) { + if (errno != EADDRINUSE) { + NETSTACK_LOGE("bind error is %{public}s %{public}d", strerror(errno), errno); + context->SetErrorCode(errno); + return false; + } + if (addr->sa_family == AF_INET) { + NETSTACK_LOGI("distribute a random port"); + addr4.sin_port = 0; /* distribute a random port */ + } else if (addr->sa_family == AF_INET6) { + NETSTACK_LOGI("distribute a random port"); + addr6.sin6_port = 0; /* distribute a random port */ + } + if (bind(context->GetSocketFd(), (const sockaddr *)addr, len) < 0) { + NETSTACK_LOGE("rebind error is %{public}s %{public}d", strerror(errno), errno); + context->SetErrorCode(errno); + return false; + } + NETSTACK_LOGI("rebind success"); + return true; + } + NETSTACK_LOGI("bind success"); + return true; +} + +bool ExecUdpSend(UdpSendContext *context) +{ + sockaddr_in addr4 = {0}; + sockaddr_in6 addr6 = {0}; + sockaddr *addr = nullptr; + socklen_t len; + GetAddr(&context->options.address, &addr4, &addr6, &addr, &len); + if (addr == nullptr) { + NETSTACK_LOGE("addr family error"); + context->SetErrorCode(ADDRESS_INVALID); + return false; + } + + if (!PollSendData(context->GetSocketFd(), context->options.GetData().c_str(), context->options.GetData().size(), + addr, len)) { + context->SetErrorCode(errno); + return false; + } + return true; +} + +bool ExecConnect(ConnectContext *context) +{ + sockaddr_in addr4 = {0}; + sockaddr_in6 addr6 = {0}; + sockaddr *addr = nullptr; + socklen_t len; + GetAddr(&context->options.address, &addr4, &addr6, &addr, &len); + if (addr == nullptr) { + NETSTACK_LOGE("addr family error"); + context->SetErrorCode(ADDRESS_INVALID); + return false; + } + + if (!NonBlockConnect(context->GetSocketFd(), addr, len, context->options.GetTimeout())) { + NETSTACK_LOGE("connect errno %{public}d %{public}s", errno, strerror(errno)); + context->SetErrorCode(errno); + return false; + } + + NETSTACK_LOGI("connect success"); + return true; +} + +bool ExecTcpSend(TcpSendContext *context) +{ + std::string encoding = context->options.GetEncoding(); + (void)encoding; + /* no use for now */ + + sa_family_t family; + socklen_t len = sizeof(sa_family_t); + if (getsockname(context->GetSocketFd(), (sockaddr *)&family, &len) < 0) { + NETSTACK_LOGE("get sock name failed"); + context->SetErrorCode(ADDRESS_INVALID); + return false; + } + bool connected = false; + if (family == AF_INET) { + sockaddr_in addr4 = {0}; + socklen_t len4 = sizeof(addr4); + int ret = getpeername(context->GetSocketFd(), (sockaddr *)&addr4, &len4); + if (ret >= 0 && addr4.sin_port != 0) { + connected = true; + } + } else if (family == AF_INET6) { + sockaddr_in6 addr6 = {0}; + socklen_t len6 = sizeof(addr6); + int ret = getpeername(context->GetSocketFd(), (sockaddr *)&addr6, &len6); + if (ret >= 0 && addr6.sin6_port != 0) { + connected = true; + } + } + + if (!connected) { + NETSTACK_LOGE("sock is not connect to remote %{public}s", strerror(errno)); + context->SetErrorCode(errno); + return false; + } + + if (!PollSendData(context->GetSocketFd(), context->options.GetData().c_str(), context->options.GetData().size(), + nullptr, 0)) { + NETSTACK_LOGE("send errno %{public}d %{public}s", errno, strerror(errno)); + context->SetErrorCode(errno); + return false; + } + return true; +} + +bool ExecClose(CloseContext *context) +{ + (void)context; + + return true; +} + +bool ExecGetState(GetStateContext *context) +{ + int opt; + socklen_t optLen = sizeof(int); + int r = getsockopt(context->GetSocketFd(), SOL_SOCKET, SO_TYPE, &opt, &optLen); + if (r < 0) { + context->state.SetIsClose(true); + return true; + } + + sa_family_t family; + socklen_t len = sizeof(family); + int ret = getsockname(context->GetSocketFd(), (sockaddr *)&family, &len); + if (ret < 0) { + context->SetErrorCode(errno); + return false; + } + + sockaddr_in addr4 = {0}; + sockaddr_in6 addr6 = {0}; + sockaddr *addr = nullptr; + socklen_t addrLen; + if (family == AF_INET) { + addr = (sockaddr *)&addr4; + addrLen = sizeof(addr4); + } else if (family == AF_INET6) { + addr = (sockaddr *)&addr6; + addrLen = sizeof(addr6); + } + + if (addr == nullptr) { + context->SetErrorCode(ADDRESS_INVALID); + return false; + } + + (void)memset_s(addr, addrLen, 0, addrLen); + len = addrLen; + ret = getsockname(context->GetSocketFd(), addr, &len); + if (ret < 0) { + context->SetErrorCode(errno); + return false; + } + + if (family == AF_INET) { + if (ntohs(addr4.sin_port) != 0) { + context->state.SetIsBound(true); + } + } else if (family == AF_INET6) { + if (ntohs(addr6.sin6_port) != 0) { + context->state.SetIsBound(true); + } + } + + if (opt != SOCK_STREAM) { + return true; + } + + (void)memset_s(addr, addrLen, 0, addrLen); + len = addrLen; + ret = getpeername(context->GetSocketFd(), addr, &len); + if (ret < 0) { + context->SetErrorCode(errno); + return false; + } + + if (family == AF_INET) { + if (ntohs(addr4.sin_port) != 0) { + context->state.SetIsConnected(true); + } + } else if (family == AF_INET6) { + if (ntohs(addr6.sin6_port) != 0) { + context->state.SetIsConnected(true); + } + } + + return true; +} + +bool ExecGetRemoteAddress(GetRemoteAddressContext *context) +{ + sa_family_t family; + socklen_t len = sizeof(family); + int ret = getsockname(context->GetSocketFd(), (sockaddr *)&family, &len); + if (ret < 0) { + context->SetErrorCode(errno); + return false; + } + + if (family == AF_INET) { + sockaddr_in addr4 = {0}; + socklen_t len4 = sizeof(sockaddr_in); + + ret = getpeername(context->GetSocketFd(), (sockaddr *)&addr4, &len4); + if (ret < 0) { + context->SetErrorCode(errno); + return false; + } + + std::string address = MakeAddressString((sockaddr *)&addr4); + if (address.empty()) { + context->SetErrorCode(ADDRESS_INVALID); + return false; + } + context->address.SetAddress(address); + context->address.SetFamilyBySaFamily(family); + context->address.SetPort(ntohs(addr4.sin_port)); + return true; + } else if (family == AF_INET6) { + sockaddr_in6 addr6 = {0}; + socklen_t len6 = sizeof(sockaddr_in6); + + ret = getpeername(context->GetSocketFd(), (sockaddr *)&addr6, &len6); + if (ret < 0) { + context->SetErrorCode(errno); + return false; + } + + std::string address = MakeAddressString((sockaddr *)&addr6); + if (address.empty()) { + context->SetErrorCode(ADDRESS_INVALID); + return false; + } + context->address.SetAddress(address); + context->address.SetFamilyBySaFamily(family); + context->address.SetPort(ntohs(addr6.sin6_port)); + return true; + } + + return false; +} + +bool ExecTcpSetExtraOptions(TcpSetExtraOptionsContext *context) +{ + if (!SetBaseOptions(context->GetSocketFd(), &context->options)) { + context->SetErrorCode(errno); + return false; + } + + if (context->options.IsKeepAlive()) { + int keepalive = 1; + if (setsockopt(context->GetSocketFd(), SOL_SOCKET, SO_KEEPALIVE, (void *)&keepalive, sizeof(keepalive)) < 0) { + context->SetErrorCode(errno); + return false; + } + } + + if (context->options.IsOOBInline()) { + int oobInline = 1; + if (setsockopt(context->GetSocketFd(), SOL_SOCKET, SO_OOBINLINE, (void *)&oobInline, sizeof(oobInline)) < 0) { + context->SetErrorCode(errno); + return false; + } + } + + if (context->options.IsTCPNoDelay()) { + int tcpNoDelay = 1; + if (setsockopt(context->GetSocketFd(), IPPROTO_TCP, TCP_NODELAY, (void *)&tcpNoDelay, sizeof(tcpNoDelay)) < 0) { + context->SetErrorCode(errno); + return false; + } + } + + linger soLinger = {0}; + soLinger.l_onoff = context->options.socketLinger.IsOn(); + soLinger.l_linger = (int)context->options.socketLinger.GetLinger(); + if (setsockopt(context->GetSocketFd(), SOL_SOCKET, SO_LINGER, &soLinger, sizeof(soLinger)) < 0) { + context->SetErrorCode(errno); + return false; + } + + return true; +} + +bool ExecUdpSetExtraOptions(UdpSetExtraOptionsContext *context) +{ + if (!SetBaseOptions(context->GetSocketFd(), &context->options)) { + context->SetErrorCode(errno); + return false; + } + + if (context->options.IsBroadcast()) { + int broadcast = 1; + if (setsockopt(context->GetSocketFd(), SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast)) < 0) { + context->SetErrorCode(errno); + return false; + } + } + + return true; +} + +napi_value BindCallback(BindContext *context) +{ + return NapiUtils::GetUndefined(context->GetEnv()); +} + +napi_value UdpSendCallback(UdpSendContext *context) +{ + sa_family_t family; + socklen_t len = sizeof(family); + int ret = getsockname(context->GetSocketFd(), (sockaddr *)&family, &len); + if (ret < 0) { + return NapiUtils::GetUndefined(context->GetEnv()); + } + if (family == AF_INET) { + sockaddr_in addr4 = {0}; + if (!PollRecvData(context->GetSocketFd(), (sockaddr *)&addr4, sizeof(addr4), UdpMessageCallback(context))) { + EmitError(context, errno); + } + return NapiUtils::GetUndefined(context->GetEnv()); + } else if (family == AF_INET6) { + sockaddr_in6 addr6 = {0}; + if (!PollRecvData(context->GetSocketFd(), (sockaddr *)&addr6, sizeof(addr6), UdpMessageCallback(context))) { + EmitError(context, errno); + } + return NapiUtils::GetUndefined(context->GetEnv()); + } + + return NapiUtils::GetUndefined(context->GetEnv()); +} + +napi_value ConnectCallback(ConnectContext *context) +{ + if (!PollRecvData(context->GetSocketFd(), nullptr, 0, TcpMessageCallback(context))) { + EmitError(context, errno); + } + return NapiUtils::GetUndefined(context->GetEnv()); +} + +napi_value TcpSendCallback(TcpSendContext *context) +{ + if (!PollRecvData(context->GetSocketFd(), nullptr, 0, TcpMessageCallback(context))) { + EmitError(context, errno); + } + return NapiUtils::GetUndefined(context->GetEnv()); +} + +napi_value CloseCallback(CloseContext *context) +{ + int ret = close(context->GetSocketFd()); + if (ret < 0) { + NETSTACK_LOGE("sock closed error %{public}s sock = %{public}d, ret = %{public}d", strerror(errno), + context->GetSocketFd(), ret); + } else { + NETSTACK_LOGI("sock %{public}d closed success", context->GetSocketFd()); + } + context->SetSocketFd(0); + return NapiUtils::GetUndefined(context->GetEnv()); +} + +napi_value GetStateCallback(GetStateContext *context) +{ + napi_value obj = NapiUtils::CreateObject(context->GetEnv()); + if (NapiUtils::GetValueType(context->GetEnv(), obj) != napi_object) { + return NapiUtils::GetUndefined(context->GetEnv()); + } + + NapiUtils::SetBooleanProperty(context->GetEnv(), obj, KEY_IS_BOUND, context->state.IsBound()); + NapiUtils::SetBooleanProperty(context->GetEnv(), obj, KEY_IS_CLOSE, context->state.IsClose()); + NapiUtils::SetBooleanProperty(context->GetEnv(), obj, KEY_IS_CONNECTED, context->state.IsConnected()); + + return obj; +} + +napi_value GetRemoteAddressCallback(GetRemoteAddressContext *context) +{ + napi_value obj = NapiUtils::CreateObject(context->GetEnv()); + if (NapiUtils::GetValueType(context->GetEnv(), obj) != napi_object) { + return NapiUtils::GetUndefined(context->GetEnv()); + } + + NapiUtils::SetStringPropertyUtf8(context->GetEnv(), obj, KEY_ADDRESS, context->address.GetAddress()); + NapiUtils::SetUint32Property(context->GetEnv(), obj, KEY_FAMILY, context->address.GetJsValueFamily()); + NapiUtils::SetUint32Property(context->GetEnv(), obj, KEY_PORT, context->address.GetPort()); + + return obj; +} + +napi_value TcpSetExtraOptionsCallback(TcpSetExtraOptionsContext *context) +{ + return NapiUtils::GetUndefined(context->GetEnv()); +} + +napi_value UdpSetExtraOptionsCallback(UdpSetExtraOptionsContext *context) +{ + return NapiUtils::GetUndefined(context->GetEnv()); +} + +} // namespace OHOS::NetStack::SocketExec diff --git a/frameworks/js/napi/socket/socket_module/include/socket_module.h b/frameworks/js/napi/socket/socket_module/include/socket_module.h new file mode 100644 index 0000000000000000000000000000000000000000..6184bbb537a0858ed3f46ce10f4e57ceef6b5f68 --- /dev/null +++ b/frameworks/js/napi/socket/socket_module/include/socket_module.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2021-2022 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_SOCKET_MODULE_H +#define COMMUNICATIONNETSTACK_SOCKET_MODULE_H + +#include "napi/native_api.h" + +namespace OHOS::NetStack { + +class SocketModuleExports { +public: + class UDPSocket { + public: + static constexpr const char *FUNCTION_BIND = "bind"; + static constexpr const char *FUNCTION_SEND = "send"; + static constexpr const char *FUNCTION_CLOSE = "close"; + static constexpr const char *FUNCTION_GET_STATE = "getState"; + static constexpr const char *FUNCTION_SET_EXTRA_OPTIONS = "setExtraOptions"; + static constexpr const char *FUNCTION_ON = "on"; + static constexpr const char *FUNCTION_OFF = "off"; + + 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 Close(napi_env env, napi_callback_info info); + static napi_value GetState(napi_env env, napi_callback_info info); + static napi_value SetExtraOptions(napi_env env, napi_callback_info info); + static napi_value On(napi_env env, napi_callback_info info); + static napi_value Off(napi_env env, napi_callback_info info); + }; + + class TCPSocket { + public: + static constexpr const char *FUNCTION_BIND = "bind"; + static constexpr const char *FUNCTION_CONNECT = "connect"; + static constexpr const char *FUNCTION_SEND = "send"; + static constexpr const char *FUNCTION_CLOSE = "close"; + static constexpr const char *FUNCTION_GET_REMOTE_ADDRESS = "getRemoteAddress"; + static constexpr const char *FUNCTION_GET_STATE = "getState"; + static constexpr const char *FUNCTION_SET_EXTRA_OPTIONS = "setExtraOptions"; + static constexpr const char *FUNCTION_ON = "on"; + static constexpr const char *FUNCTION_OFF = "off"; + + 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 Close(napi_env env, napi_callback_info info); + static napi_value GetRemoteAddress(napi_env env, napi_callback_info info); + static napi_value GetState(napi_env env, napi_callback_info info); + static napi_value SetExtraOptions(napi_env env, napi_callback_info info); + static napi_value On(napi_env env, napi_callback_info info); + static napi_value Off(napi_env env, napi_callback_info info); + }; + + static constexpr const char *FUNCTION_CONSTRUCTOR_UDP_SOCKET_INSTANCE = "constructUDPSocketInstance"; + static constexpr const char *FUNCTION_CONSTRUCTOR_TCP_SOCKET_INSTANCE = "constructTCPSocketInstance"; + static constexpr const char *INTERFACE_UDP_SOCKET = "UDPSocket"; + static constexpr const char *INTERFACE_TCP_SOCKET = "TCPSocket"; + + static napi_value InitSocketModule(napi_env env, napi_value exports); + +private: + static napi_value ConstructUDPSocketInstance(napi_env env, napi_callback_info info); + + static napi_value ConstructTCPSocketInstance(napi_env env, napi_callback_info info); + + static void DefineUDPSocketClass(napi_env env, napi_value exports); + + static void DefineTCPSocketClass(napi_env env, napi_value exports); + + static void InitSocketProperties(napi_env env, napi_value exports); +}; + +} // namespace OHOS::NetStack +#endif // COMMUNICATIONNETSTACK_SOCKET_MODULE_H \ No newline at end of file diff --git a/frameworks/js/napi/socket/socket_module/src/socket_module.cpp b/frameworks/js/napi/socket/socket_module/src/socket_module.cpp new file mode 100644 index 0000000000000000000000000000000000000000..735f99a3661b9a66cb3e3226eb2e6b61b2863267 --- /dev/null +++ b/frameworks/js/napi/socket/socket_module/src/socket_module.cpp @@ -0,0 +1,295 @@ +/* + * Copyright (C) 2021-2022 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 "socket_module.h" + +#include "context_key.h" +#include "event_list.h" +#include "netstack_log.h" +#include "netstack_module_template.h" +#include "socket_async_work.h" +#include "socket_exec.h" +#include "task_queue.h" +#include + +#define SOCKET_MODULE_NAME "net.socket" + +#define SOCKET_INTERFACE(Context, executor, callback, work, priority) \ + ModuleTemplate::InterfaceWithOutAsyncWork( \ + env, info, \ + PushTask) + +#define FINALIZER(protocol) \ + [](napi_env, void *data, void *) { \ + NETSTACK_LOGI(#protocol "socket handle is finalized"); \ + auto manager = static_cast(data); \ + if (manager != nullptr) { \ + int sock = (int)(uint64_t)manager->GetData(); \ + if (sock != 0) { \ + close(sock); \ + } \ + } \ + delete manager; \ + } + +namespace OHOS::NetStack { + +template +bool PushTask(napi_env env, napi_value thisVal, Context *context) +{ + static_assert(std::is_base_of::value); + + if (Work != nullptr && !Work(env, thisVal, context)) { + return false; + } + Task::PushTask(priority, executor, callback, context); + return true; +} + +static bool SetSocket(napi_env env, napi_value thisVal, BindContext *context, int sock) +{ + if (sock < 0) { + napi_value error = NapiUtils::CreateObject(env); + if (NapiUtils::GetValueType(env, error) != napi_object) { + return false; + } + NapiUtils::SetUint32Property(env, error, KEY_ERROR_CODE, errno); + context->Emit(EVENT_ERROR, std::make_pair(NapiUtils::GetUndefined(env), error)); + return false; + } + + EventManager *manager = nullptr; + if (napi_unwrap(env, thisVal, reinterpret_cast(&manager)) != napi_ok || manager == nullptr) { + return false; + } + + manager->SetData(reinterpret_cast(sock)); + return true; +} + +static bool MakeTcpSocket(napi_env env, napi_value thisVal, BindContext *context) +{ + int sock = SocketExec::MakeTcpSocket(context->address.GetSaFamily()); + if (!SetSocket(env, thisVal, context, sock)) { + return false; + } + context->SetExecOK(true); + return true; +} + +static bool MakeUdpSocket(napi_env env, napi_value thisVal, BindContext *context) +{ + int sock = SocketExec::MakeUdpSocket(context->address.GetSaFamily()); + if (!SetSocket(env, thisVal, context, sock)) { + return false; + } + context->SetExecOK(true); + return true; +} + +napi_value SocketModuleExports::InitSocketModule(napi_env env, napi_value exports) +{ + DefineUDPSocketClass(env, exports); + DefineTCPSocketClass(env, exports); + InitSocketProperties(env, exports); + + return exports; +} + +napi_value SocketModuleExports::ConstructUDPSocketInstance(napi_env env, napi_callback_info info) +{ + return ModuleTemplate::NewInstance(env, info, INTERFACE_UDP_SOCKET, FINALIZER(Udp)); +} + +void SocketModuleExports::DefineUDPSocketClass(napi_env env, napi_value exports) +{ + std::initializer_list properties = { + DECLARE_NAPI_FUNCTION(UDPSocket::FUNCTION_BIND, UDPSocket::Bind), + DECLARE_NAPI_FUNCTION(UDPSocket::FUNCTION_SEND, UDPSocket::Send), + DECLARE_NAPI_FUNCTION(UDPSocket::FUNCTION_CLOSE, UDPSocket::Close), + DECLARE_NAPI_FUNCTION(UDPSocket::FUNCTION_GET_STATE, UDPSocket::GetState), + DECLARE_NAPI_FUNCTION(UDPSocket::FUNCTION_SET_EXTRA_OPTIONS, UDPSocket::SetExtraOptions), + DECLARE_NAPI_FUNCTION(UDPSocket::FUNCTION_ON, UDPSocket::On), + DECLARE_NAPI_FUNCTION(UDPSocket::FUNCTION_OFF, UDPSocket::Off), + }; + ModuleTemplate::DefineClass(env, exports, properties, INTERFACE_UDP_SOCKET); +} + +napi_value SocketModuleExports::ConstructTCPSocketInstance(napi_env env, napi_callback_info info) +{ + return ModuleTemplate::NewInstance(env, info, INTERFACE_TCP_SOCKET, FINALIZER(Tcp)); +} + +void SocketModuleExports::DefineTCPSocketClass(napi_env env, napi_value exports) +{ + std::initializer_list properties = { + DECLARE_NAPI_FUNCTION(TCPSocket::FUNCTION_BIND, TCPSocket::Bind), + DECLARE_NAPI_FUNCTION(TCPSocket::FUNCTION_CONNECT, TCPSocket::Connect), + DECLARE_NAPI_FUNCTION(TCPSocket::FUNCTION_SEND, TCPSocket::Send), + DECLARE_NAPI_FUNCTION(TCPSocket::FUNCTION_CLOSE, TCPSocket::Close), + DECLARE_NAPI_FUNCTION(TCPSocket::FUNCTION_GET_REMOTE_ADDRESS, TCPSocket::GetRemoteAddress), + DECLARE_NAPI_FUNCTION(TCPSocket::FUNCTION_GET_STATE, TCPSocket::GetState), + DECLARE_NAPI_FUNCTION(TCPSocket::FUNCTION_SET_EXTRA_OPTIONS, TCPSocket::SetExtraOptions), + DECLARE_NAPI_FUNCTION(TCPSocket::FUNCTION_ON, TCPSocket::On), + DECLARE_NAPI_FUNCTION(TCPSocket::FUNCTION_OFF, TCPSocket::Off), + }; + ModuleTemplate::DefineClass(env, exports, properties, INTERFACE_TCP_SOCKET); +} + +void SocketModuleExports::InitSocketProperties(napi_env env, napi_value exports) +{ + std::initializer_list properties = { + DECLARE_NAPI_FUNCTION(FUNCTION_CONSTRUCTOR_UDP_SOCKET_INSTANCE, ConstructUDPSocketInstance), + DECLARE_NAPI_FUNCTION(FUNCTION_CONSTRUCTOR_TCP_SOCKET_INSTANCE, ConstructTCPSocketInstance), + }; + NapiUtils::DefineProperties(env, exports, properties); +} + +/* udp async works */ +napi_value SocketModuleExports::UDPSocket::Bind(napi_env env, napi_callback_info info) +{ + auto ret = SOCKET_INTERFACE(BindContext, ExecBind, BindCallback, MakeUdpSocket, BIND); + auto baseContext = new BaseContext(env, nullptr); + baseContext->CreateAsyncWork("UdpBind", Task::Executor, Task::Callback); + return ret; +} + +napi_value SocketModuleExports::UDPSocket::Send(napi_env env, napi_callback_info info) +{ + auto ret = SOCKET_INTERFACE(UdpSendContext, ExecUdpSend, UdpSendCallback, nullptr, SEND); + auto baseContext = new BaseContext(env, nullptr); + baseContext->CreateAsyncWork("UdpSend", Task::Executor, Task::Callback); + return ret; +} + +napi_value SocketModuleExports::UDPSocket::Close(napi_env env, napi_callback_info info) +{ + auto ret = SOCKET_INTERFACE(CloseContext, ExecClose, CloseCallback, nullptr, CLOSE); + auto baseContext = new BaseContext(env, nullptr); + baseContext->CreateAsyncWork("UdpClose", Task::Executor, Task::Callback); + return ret; +} + +napi_value SocketModuleExports::UDPSocket::GetState(napi_env env, napi_callback_info info) +{ + return ModuleTemplate::Interface(env, info, "UdpGetState", nullptr, SocketAsyncWork::ExecGetState, + SocketAsyncWork::GetStateCallback); +} + +napi_value SocketModuleExports::UDPSocket::SetExtraOptions(napi_env env, napi_callback_info info) +{ + auto ret = SOCKET_INTERFACE(UdpSetExtraOptionsContext, ExecUdpSetExtraOptions, UdpSetExtraOptionsCallback, nullptr, + SET_OPTIONS); + auto baseContext = new BaseContext(env, nullptr); + baseContext->CreateAsyncWork("UdpSetExtraOptions", Task::Executor, Task::Callback); + return ret; +} + +napi_value SocketModuleExports::UDPSocket::On(napi_env env, napi_callback_info info) +{ + return ModuleTemplate::On(env, info, {EVENT_MESSAGE, EVENT_LISTENING, EVENT_ERROR}, false); +} + +napi_value SocketModuleExports::UDPSocket::Off(napi_env env, napi_callback_info info) +{ + return ModuleTemplate::Off(env, info, {EVENT_MESSAGE, EVENT_LISTENING, EVENT_ERROR}); +} + +/* tcp async works */ +napi_value SocketModuleExports::TCPSocket::Bind(napi_env env, napi_callback_info info) +{ + auto ret = SOCKET_INTERFACE(BindContext, ExecBind, BindCallback, MakeTcpSocket, BIND); + auto baseContext = new BaseContext(env, nullptr); + baseContext->CreateAsyncWork("TcpBind", Task::Executor, Task::Callback); + return ret; +} + +napi_value SocketModuleExports::TCPSocket::Connect(napi_env env, napi_callback_info info) +{ + auto ret = SOCKET_INTERFACE(ConnectContext, ExecConnect, ConnectCallback, nullptr, CONNECT); + auto baseContext = new BaseContext(env, nullptr); + baseContext->CreateAsyncWork("TcpConnect", Task::Executor, Task::Callback); + return ret; +} + +napi_value SocketModuleExports::TCPSocket::Send(napi_env env, napi_callback_info info) +{ + auto baseContext = new BaseContext(env, nullptr); + baseContext->CreateAsyncWork("TcpSend", Task::Executor, Task::Callback); + return SOCKET_INTERFACE(TcpSendContext, ExecTcpSend, TcpSendCallback, nullptr, SEND); +} + +napi_value SocketModuleExports::TCPSocket::Close(napi_env env, napi_callback_info info) +{ + auto ret = SOCKET_INTERFACE(CloseContext, ExecClose, CloseCallback, nullptr, CLOSE); + auto baseContext = new BaseContext(env, nullptr); + baseContext->CreateAsyncWork("TcpClose", Task::Executor, Task::Callback); + return ret; +} + +napi_value SocketModuleExports::TCPSocket::GetRemoteAddress(napi_env env, napi_callback_info info) +{ + return ModuleTemplate::Interface(env, info, "UdpGetRemoteAddress", nullptr, + SocketAsyncWork::ExecGetRemoteAddress, + SocketAsyncWork::GetRemoteAddressCallback); +} + +napi_value SocketModuleExports::TCPSocket::GetState(napi_env env, napi_callback_info info) +{ + return ModuleTemplate::Interface(env, info, "TcpGetState", nullptr, SocketAsyncWork::ExecGetState, + SocketAsyncWork::GetStateCallback); +} + +napi_value SocketModuleExports::TCPSocket::SetExtraOptions(napi_env env, napi_callback_info info) +{ + auto ret = SOCKET_INTERFACE(TcpSetExtraOptionsContext, ExecTcpSetExtraOptions, TcpSetExtraOptionsCallback, nullptr, + SET_OPTIONS); + auto baseContext = new BaseContext(env, nullptr); + baseContext->CreateAsyncWork("TcpSetExtraOptions", Task::Executor, Task::Callback); + return ret; +} + +napi_value SocketModuleExports::TCPSocket::On(napi_env env, napi_callback_info info) +{ + return ModuleTemplate::On(env, info, {EVENT_MESSAGE, EVENT_CONNECT, EVENT_ERROR}, false); +} + +napi_value SocketModuleExports::TCPSocket::Off(napi_env env, napi_callback_info info) +{ + return ModuleTemplate::Off(env, info, {EVENT_MESSAGE, EVENT_CONNECT, EVENT_ERROR}); +} + +static napi_module g_socketModule = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = SocketModuleExports::InitSocketModule, + .nm_modname = SOCKET_MODULE_NAME, + .nm_priv = nullptr, + .reserved = {nullptr}, +}; +/* + * Module register function + */ +extern "C" __attribute__((constructor)) void RegisterSocketModule(void) +{ + napi_module_register(&g_socketModule); +} + +} // namespace OHOS::NetStack \ No newline at end of file diff --git a/frameworks/js/napi/socket/src/socket_napi.cpp b/frameworks/js/napi/socket/src/socket_napi.cpp deleted file mode 100644 index a6bf0200237a7b24c7a68c6ba5575f36e572243b..0000000000000000000000000000000000000000 --- a/frameworks/js/napi/socket/src/socket_napi.cpp +++ /dev/null @@ -1,2122 +0,0 @@ -/* - * Copyright (C) 2021 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 "socket_napi.h" - -#include "napi_util.h" -#include "netmgr_log_wrapper.h" -#include "node_api_types.h" - -#include "tcp_socket.h" -#include "udp_socket.h" - -#include -#include -#include -#include - -namespace OHOS { -namespace NetManagerStandard { -static napi_value g_UdpSocketConstructorJS; -static napi_value g_TcpSocketConstructorJS; -std::vector g_onInfoList; -std::vector g_tcpSocketList; -static std::map udpSocketInstances; -static std::map tcpSocketInstances; -constexpr int32_t INVALID_SOCKET = -1; -constexpr int32_t EVENT_ARRAY_LENGTH = 64; - -constexpr int32_t NONE_EVENT_TYPE = 0; -constexpr int32_t MESSAGE_SOCKET_STATE = 1; -constexpr int32_t LISTENING_SOCKET_STATE = 2; -constexpr int32_t CLOSE_SOCKET_STATE = 3; -constexpr int32_t ERROR_SOCKET_STATE = 4; -constexpr int32_t CONNECT_SOCKET_STATE = 5; - -const std::string MESSAGE_RECEIVE = "message"; -const std::string LISTENING_RECEIVE = "listening"; -const std::string CLOSE_RECEIVE = "close"; -const std::string ERROR_RECEIVE = "error"; -const std::string CONNECT_RECEIVE = "connect"; - -constexpr int32_t MAX_SOCKET_OBJ_COUNT = 100; - -bool MatchSocketEventType(const std::string &type, const std::string &goalTypeStr) -{ - return goalTypeStr.compare(type) == 0; -} - -int32_t GetSocketEventType(const std::string &type) -{ - if (MatchSocketEventType(type, MESSAGE_RECEIVE)) { - return MESSAGE_SOCKET_STATE; - } else if (MatchSocketEventType(type, LISTENING_RECEIVE)) { - return LISTENING_SOCKET_STATE; - } else if (MatchSocketEventType(type, CLOSE_RECEIVE)) { - return CLOSE_SOCKET_STATE; - } else if (MatchSocketEventType(type, ERROR_RECEIVE)) { - return ERROR_SOCKET_STATE; - } else if (MatchSocketEventType(type, CONNECT_RECEIVE)) { - return CONNECT_SOCKET_STATE; - } - return NONE_EVENT_TYPE; -} - -static void EmitUdpEvent(UDPSocket *obj, const std::string &type, const std::string &message) -{ - int32_t eventType = GetSocketEventType(type); - for (std::list::iterator listenerIterator = g_udpEventListenerList.begin(); - listenerIterator != g_udpEventListenerList.end(); ++listenerIterator) { - if (listenerIterator->udpSocket_ == obj && listenerIterator->eventType_ == eventType) { - napi_env env = listenerIterator->env_; - napi_handle_scope scope = nullptr; - napi_open_handle_scope(env, &scope); - napi_value undefine = nullptr; - napi_get_undefined(env, &undefine); - napi_ref callbackRef = listenerIterator->callbackRef_; - napi_value callbackFunc = nullptr; - napi_get_reference_value(env, callbackRef, &callbackFunc); - napi_value callbackValues[2] = {0}; - - callbackValues[0] = NapiUtil::CreateUndefined(env); - napi_value object = nullptr; - napi_create_object(env, &object); - NapiUtil::SetPropertyStringUtf8(env, object, type, message); - - callbackValues[1] = object; - napi_value callbackResult = nullptr; - napi_call_function(env, undefine, callbackFunc, PARAMS_COUNT, callbackValues, &callbackResult); - napi_close_handle_scope(env, scope); - napi_delete_reference(env, listenerIterator->callbackRef_); - break; - } - } -} - -static void NativeUdpBind(napi_env env, void *data) -{ - if (data == nullptr) { - NETMGR_LOGE("NativeUdpBind formal parameter data is null"); - return; - } - auto asyncContext = static_cast(data); - struct sockaddr_in addr; - asyncContext->udpRequestInfo_->GetSocketInfo(addr, asyncContext); - - if (!asyncContext->isBound && asyncContext->isClose && !asyncContext->isConnected) { - asyncContext->errorCode = asyncContext->udpRequestInfo_->UdpBind(asyncContext->socketfd, - (struct sockaddr *)&addr, sizeof(struct sockaddr)); - } - if (asyncContext->errorCode >= 0) { - asyncContext->isBound = true; - asyncContext->resolved_ = true; - std::string listening("listening"); - EmitUdpEvent(asyncContext->udpRequestInfo_, "listening", listening); - } else { - std::string error("error"); - EmitUdpEvent(asyncContext->udpRequestInfo_, "error", error); - } -} - -static void UdpBindCallback(napi_env env, napi_status status, void *data) -{ - if (data == nullptr) { - NETMGR_LOGE("UdpBindCallback data parameter address is nullptr"); - return; - } - auto asyncContext = static_cast(data); - napi_value callbackValue = nullptr; - - if (asyncContext->resolved_) { - napi_create_object(env, &callbackValue); - NapiUtil::SetPropertyInt32(env, callbackValue, "errorCode", asyncContext->errorCode); - } else { - callbackValue = NapiUtil::CreateErrorMessage(env, "bind failed"); - } - if (asyncContext->callbackRef_ != nullptr) { - napi_value callbackFunc = nullptr; - napi_get_reference_value(env, asyncContext->callbackRef_, &callbackFunc); - napi_value callbackValues[] = {nullptr, nullptr}; - callbackValues[0] = asyncContext->resolved_ ? NapiUtil::CreateUndefined(env) : callbackValue; - callbackValues[1] = asyncContext->resolved_ ? callbackValue : NapiUtil::CreateUndefined(env); - napi_value undefined = nullptr; - napi_value callback = nullptr; - napi_value result = nullptr; - NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); - NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, asyncContext->callbackRef_, &callback)); - NAPI_CALL_RETURN_VOID( - env, napi_call_function(env, undefined, callback, std::size(callbackValues), callbackValues, &result)); - NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, asyncContext->callbackRef_)); - } else if (asyncContext->deferred_ != nullptr) { - if (asyncContext->resolved_) { - napi_resolve_deferred(env, asyncContext->deferred_, callbackValue); - } else { - napi_reject_deferred(env, asyncContext->deferred_, callbackValue); - } - } - - napi_delete_async_work(env, asyncContext->work_); -} - -static void NativeUdpConnect(napi_env env, void *data) -{ - if (data == nullptr) { - NETMGR_LOGE("NativeUdpConnect formal parameter data is null"); - return; - } - auto asyncContext = static_cast(data); - struct sockaddr_in addr; - asyncContext->udpRequestInfo_->GetSocketInfo(addr, asyncContext); - // the init isclose=true and if fd close we can bind also - if (!asyncContext->isBound && asyncContext->isClose && !asyncContext->isConnected) { - asyncContext->errorCode = asyncContext->udpRequestInfo_->UdpConnect(asyncContext->socketfd, - (struct sockaddr *)&addr, sizeof(struct sockaddr)); - } - if (asyncContext->errorCode >= 0) { - asyncContext->isConnected = true; - // Once Connect Success ,the close state must false - asyncContext->isClose = false; - } -} - -static void UdpConnectCallback(napi_env env, napi_status status, void *data) -{ - if (data == nullptr) { - NETMGR_LOGE("UdpConnectCallback data parameter address is nullptr"); - return; - } - auto asyncContext = static_cast(data); - napi_value callbackValue = nullptr; - - if (asyncContext->resolved_) { - napi_create_object(env, &callbackValue); - NapiUtil::SetPropertyInt32(env, callbackValue, "errorCode", asyncContext->errorCode); - } else { - callbackValue = NapiUtil::CreateErrorMessage(env, "udp connect failed"); - } - if (asyncContext->callbackRef_ != nullptr) { - napi_value callbackFunc = nullptr; - napi_get_reference_value(env, asyncContext->callbackRef_, &callbackFunc); - napi_value callbackValues[] = {nullptr, nullptr}; - callbackValues[0] = asyncContext->resolved_ ? NapiUtil::CreateUndefined(env) : callbackValue; - callbackValues[1] = asyncContext->resolved_ ? callbackValue : NapiUtil::CreateUndefined(env); - napi_value undefined = nullptr; - napi_value callback = nullptr; - napi_value result = nullptr; - NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); - NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, asyncContext->callbackRef_, &callback)); - NAPI_CALL_RETURN_VOID( - env, napi_call_function(env, undefined, callback, std::size(callbackValues), callbackValues, &result)); - NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, asyncContext->callbackRef_)); - } else if (asyncContext->deferred_ != nullptr) { - if (asyncContext->resolved_) { - napi_resolve_deferred(env, asyncContext->deferred_, callbackValue); - } else { - napi_reject_deferred(env, asyncContext->deferred_, callbackValue); - } - } - - napi_delete_async_work(env, asyncContext->work_); -} - -static void NativeUdpSend(napi_env env, void *data) -{ - if (data == nullptr) { - NETMGR_LOGE("NativeUdpBind formal parameter data is null"); - return; - } - auto asyncContext = static_cast(data); - - struct sockaddr_in addr; - asyncContext->udpRequestInfo_->GetSocketInfo(addr, asyncContext); - - if (!asyncContext->isClose) { - asyncContext->errorCode = asyncContext->udpRequestInfo_->UdpSend(asyncContext->socketfd, - asyncContext->data.c_str(), asyncContext->data.size(), 0); - } - - if (asyncContext->errorCode >= 0) { - std::string message("message"); - EmitUdpEvent(asyncContext->udpRequestInfo_, "message", message); - } else { - std::string error("error"); - EmitUdpEvent(asyncContext->udpRequestInfo_, "error", error); - } -} - -static void UdpSendCallback(napi_env env, napi_status status, void *data) -{ - if (data == nullptr) { - NETMGR_LOGE("UdpSendCallback data parameter address is nullptr"); - return; - } - auto asyncContext = static_cast(data); - napi_value callbackValue = nullptr; - - if (asyncContext->resolved_) { - napi_create_object(env, &callbackValue); - NapiUtil::SetPropertyInt32(env, callbackValue, "errorCode", asyncContext->errorCode); - } else { - callbackValue = NapiUtil::CreateErrorMessage(env, "Request failed"); - } - if (asyncContext->callbackRef_ != nullptr) { - napi_value callbackFunc = nullptr; - napi_get_reference_value(env, asyncContext->callbackRef_, &callbackFunc); - napi_value callbackValues[] = {nullptr, nullptr}; - callbackValues[0] = asyncContext->resolved_ ? NapiUtil::CreateUndefined(env) : callbackValue; - callbackValues[1] = asyncContext->resolved_ ? callbackValue : NapiUtil::CreateUndefined(env); - napi_value undefined = nullptr; - napi_value callback = nullptr; - napi_value result = nullptr; - NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); - NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, asyncContext->callbackRef_, &callback)); - NAPI_CALL_RETURN_VOID( - env, napi_call_function(env, undefined, callback, std::size(callbackValues), callbackValues, &result)); - NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, asyncContext->callbackRef_)); - } else if (asyncContext->deferred_ != nullptr) { - if (asyncContext->resolved_) { - napi_resolve_deferred(env, asyncContext->deferred_, callbackValue); - } else { - napi_reject_deferred(env, asyncContext->deferred_, callbackValue); - } - } - - napi_delete_async_work(env, asyncContext->work_); -} - -static void NativeUdpClose(napi_env env, void *data) -{ - if (data == nullptr) { - NETMGR_LOGE("NativeUdpClose formal parameter data is null"); - return; - } - auto asyncContext = static_cast(data); - - if (!asyncContext->isClose) { - asyncContext->errorCode = asyncContext->udpRequestInfo_->UdpClose(asyncContext->socketfd); - std::string close("close"); - EmitUdpEvent(asyncContext->udpRequestInfo_, "close", close); - } else { - std::string error("error"); - EmitUdpEvent(asyncContext->udpRequestInfo_, "error", error); - } -} - -static void UdpCloseCallback(napi_env env, napi_status status, void *data) -{ - if (data == nullptr) { - NETMGR_LOGE("UdpCloseCallback data parameter address is nullptr"); - return; - } - auto asyncContext = static_cast(data); - napi_value callbackValue = nullptr; - - if (asyncContext->resolved_) { - napi_create_object(env, &callbackValue); - NapiUtil::SetPropertyInt32(env, callbackValue, "errorCode", asyncContext->errorCode); - } else { - callbackValue = NapiUtil::CreateErrorMessage(env, "udp socket close failed"); - } - if (asyncContext->callbackRef_ != nullptr) { - napi_value callbackFunc = nullptr; - napi_get_reference_value(env, asyncContext->callbackRef_, &callbackFunc); - napi_value callbackValues[] = {nullptr, nullptr}; - callbackValues[0] = asyncContext->resolved_ ? NapiUtil::CreateUndefined(env) : callbackValue; - callbackValues[1] = asyncContext->resolved_ ? callbackValue : NapiUtil::CreateUndefined(env); - napi_value undefined = nullptr; - napi_value callback = nullptr; - napi_value result = nullptr; - NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); - NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, asyncContext->callbackRef_, &callback)); - NAPI_CALL_RETURN_VOID( - env, napi_call_function(env, undefined, callback, std::size(callbackValues), callbackValues, &result)); - NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, asyncContext->callbackRef_)); - } else if (asyncContext->deferred_ != nullptr) { - if (asyncContext->resolved_) { - napi_resolve_deferred(env, asyncContext->deferred_, callbackValue); - } else { - napi_reject_deferred(env, asyncContext->deferred_, callbackValue); - } - } - - napi_delete_async_work(env, asyncContext->work_); -} - -static void NativeUdpGetState(napi_env env, void *data) -{ - if (data == nullptr) { - NETMGR_LOGE("NativeUdpGetState formal parameter data is null"); - return; - } - auto asyncContext = static_cast(data); - asyncContext->resolved_ = true; -} - -static void UdpGetStateCallback(napi_env env, napi_status status, void *data) -{ - if (data == nullptr) { - NETMGR_LOGE("UdpGetStateCallback data parameter address is nullptr"); - return; - } - auto asyncContext = static_cast(data); - napi_value callbackValue = nullptr; - - if (asyncContext->resolved_) { - napi_create_object(env, &callbackValue); - NapiUtil::SetPropertyInt32(env, callbackValue, "isBound", asyncContext->isBound); - NapiUtil::SetPropertyInt32(env, callbackValue, "isClose", asyncContext->isClose); - NapiUtil::SetPropertyInt32(env, callbackValue, "isConnected", asyncContext->isConnected); - } else { - callbackValue = NapiUtil::CreateErrorMessage(env, "udp socket getState failed"); - } - if (asyncContext->callbackRef_ != nullptr) { - napi_value callbackValues[] = {nullptr, nullptr}; - callbackValues[0] = asyncContext->resolved_ ? NapiUtil::CreateUndefined(env) : callbackValue; - callbackValues[1] = asyncContext->resolved_ ? callbackValue : NapiUtil::CreateUndefined(env); - napi_value undefined = nullptr; - napi_value callback = nullptr; - napi_value result = nullptr; - NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); - NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, asyncContext->callbackRef_, &callback)); - NAPI_CALL_RETURN_VOID(env, napi_call_function(env, undefined, callback, PARAMS_COUNT, callbackValues, &result)); - NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, asyncContext->callbackRef_)); - } else if (asyncContext->deferred_ != nullptr) { - if (asyncContext->resolved_) { - napi_resolve_deferred(env, asyncContext->deferred_, callbackValue); - } else { - napi_reject_deferred(env, asyncContext->deferred_, callbackValue); - } - } - - napi_delete_async_work(env, asyncContext->work_); -} - -static void NativeUdpSetExtraOptions(napi_env env, void *data) -{ - if (data == nullptr) { - NETMGR_LOGE("NativeSetExtraOptionsSend formal parameter data is null"); - return; - } - auto asyncContext = static_cast(data); - - struct sockaddr_in addr; - asyncContext->udpRequestInfo_->GetSocketInfo(addr, asyncContext); -} - -static void UdpSetExtraOptionsCallback(napi_env env, napi_status status, void *data) -{ - if (data == nullptr) { - NETMGR_LOGE("UdpSetExtraOptionsCallback data parameter address is nullptr"); - return; - } - auto asyncContext = static_cast(data); - napi_value callbackValue = nullptr; - - if (asyncContext->resolved_) { - napi_create_object(env, &callbackValue); - NapiUtil::SetPropertyInt32(env, callbackValue, "errorCode", asyncContext->errorCode); - } else { - callbackValue = NapiUtil::CreateErrorMessage(env, "udp socket SetExtraOptions failed"); - } - if (asyncContext->callbackRef_ != nullptr) { - napi_value callbackFunc = nullptr; - napi_get_reference_value(env, asyncContext->callbackRef_, &callbackFunc); - napi_value callbackValues[] = {nullptr, nullptr}; - callbackValues[0] = asyncContext->resolved_ ? NapiUtil::CreateUndefined(env) : callbackValue; - callbackValues[1] = asyncContext->resolved_ ? callbackValue : NapiUtil::CreateUndefined(env); - napi_value undefined = nullptr; - napi_value callback = nullptr; - napi_value result = nullptr; - NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); - NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, asyncContext->callbackRef_, &callback)); - NAPI_CALL_RETURN_VOID( - env, napi_call_function(env, undefined, callback, std::size(callbackValues), callbackValues, &result)); - NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, asyncContext->callbackRef_)); - } else if (asyncContext->deferred_ != nullptr) { - if (asyncContext->resolved_) { - napi_resolve_deferred(env, asyncContext->deferred_, callbackValue); - } else { - napi_reject_deferred(env, asyncContext->deferred_, callbackValue); - } - } - - napi_delete_async_work(env, asyncContext->work_); -} - -napi_value CreateUDPSocket(napi_env env, napi_callback_info info) -{ - std::size_t argc = 2; - napi_value args[2] = { nullptr }; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr)); - - napi_value result = nullptr; - napi_value argvArray[] = {nullptr}; - napi_new_instance(env, g_UdpSocketConstructorJS, 0, argvArray, &result); - - return result; -} - -napi_value UdpBind(napi_env env, napi_callback_info info) -{ - std::size_t parameterCount = 2; - napi_value parameters[2] = {0}; - napi_value thisVar = nullptr; - void *data = nullptr; - - NAPI_CALL(env, napi_get_cb_info(env, info, ¶meterCount, parameters, &thisVar, &data)); - - Baseinfo *asyncContext = nullptr; - UDPSocket *objectInfo = nullptr; - napi_valuetype valuetype; - - NAPI_CALL(env, napi_typeof(env, thisVar, &valuetype)); - - NAPI_ASSERT(env, valuetype == napi_object, "Wrong argument type for arg0. Subscribe expected."); - napi_unwrap(env, thisVar, (void **)&objectInfo); - - auto requestKey = udpSocketInstances.find(objectInfo); - if (requestKey != udpSocketInstances.end()) { - asyncContext = requestKey->second; - } else { - NETMGR_LOGE("udpSocketInstances add udp socket pointer"); - return nullptr; - } - - objectInfo->GetJSParameter(env, parameters, asyncContext); - - if (asyncContext->family == IPV6) { - asyncContext->socketfd = objectInfo->UdpSocket(AF_INET6, SOCK_DGRAM, 0); - } else { - asyncContext->socketfd = objectInfo->UdpSocket(AF_INET, SOCK_DGRAM, 0); - } - if (asyncContext->socketfd < 0) { - return nullptr; - } - - if (parameterCount == PARAMS_COUNT) { - if (NapiUtil::MatchValueType(env, parameters[1], napi_function)) { - NAPI_CALL(env, napi_create_reference(env, parameters[1], 1, &(asyncContext->callbackRef_))); - } - } - - napi_value result = nullptr; - - if (asyncContext->callbackRef_ == nullptr) { - NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred_, &result)); - } else { - NAPI_CALL(env, napi_get_undefined(env, &result)); - } - napi_value resourceName = nullptr; - NAPI_CALL(env, napi_create_string_utf8(env, "udpBind", NAPI_AUTO_LENGTH, &resourceName)); - - NAPI_CALL(env, - napi_create_async_work(env, nullptr, resourceName, NativeUdpBind, UdpBindCallback, (void *)asyncContext, - &(asyncContext->work_))); - napi_status resultStatus = napi_queue_async_work(env, asyncContext->work_); - if (resultStatus == napi_ok) { - NETMGR_LOGI("Udp bind Async Work Successful"); - } - return result; -} - -napi_value UdpConnect(napi_env env, napi_callback_info info) -{ - std::size_t parameterCount = 2; - napi_value parameters[2] = {0}; - napi_value thisVar = nullptr; - void *data = nullptr; - - NAPI_CALL(env, napi_get_cb_info(env, info, ¶meterCount, parameters, &thisVar, &data)); - - Baseinfo *asyncContext = nullptr; - UDPSocket *objectInfo = nullptr; - napi_valuetype valuetype; - NAPI_CALL(env, napi_typeof(env, thisVar, &valuetype)); - - NAPI_ASSERT(env, valuetype == napi_object, "Wrong argument type for arg0. Subscribe expected."); - napi_unwrap(env, thisVar, (void **)&objectInfo); - - auto requestKey = udpSocketInstances.find(objectInfo); - if (requestKey != udpSocketInstances.end()) { - asyncContext = requestKey->second; - } else { - NETMGR_LOGE("UdpConnect not find socket pointer"); - return nullptr; - } - - objectInfo->GetJSParameter(env, parameters, asyncContext); - - if (parameterCount == PARAMS_COUNT) { - if (NapiUtil::MatchValueType(env, parameters[1], napi_function)) { - NAPI_CALL(env, napi_create_reference(env, parameters[1], 1, &(asyncContext->callbackRef_))); - } - } - - napi_value result = nullptr; - - if (asyncContext->callbackRef_ == nullptr) { - NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred_, &result)); - } else { - NAPI_CALL(env, napi_get_undefined(env, &result)); - } - napi_value resourceName = nullptr; - NAPI_CALL(env, napi_create_string_utf8(env, "udpConnect", NAPI_AUTO_LENGTH, &resourceName)); - - NAPI_CALL(env, - napi_create_async_work(env, nullptr, resourceName, NativeUdpConnect, UdpConnectCallback, (void *)asyncContext, - &(asyncContext->work_))); - napi_status resultStatus = napi_queue_async_work(env, asyncContext->work_); - if (resultStatus == napi_ok) { - NETMGR_LOGI("Udp connect Async Work Successful"); - } - return result; -} - -napi_value UdpSend(napi_env env, napi_callback_info info) -{ - std::size_t parameterCount = 2; - napi_value parameters[2] = {0}; - napi_value thisVar = nullptr; - void *data = nullptr; - - NAPI_CALL(env, napi_get_cb_info(env, info, ¶meterCount, parameters, &thisVar, &data)); - - Baseinfo *asyncContext = nullptr; - UDPSocket *objectInfo = nullptr; - napi_valuetype valuetype; - - NAPI_CALL(env, napi_typeof(env, thisVar, &valuetype)); - - NAPI_ASSERT(env, valuetype == napi_object, "Wrong argument type for arg0. Subscribe expected."); - napi_unwrap(env, thisVar, (void **)&objectInfo); - - auto requestKey = udpSocketInstances.find(objectInfo); - if (requestKey != udpSocketInstances.end()) { - asyncContext = requestKey->second; - } else { - NETMGR_LOGE("UdpSend not find socket pointer"); - return nullptr; - } - - objectInfo->GetJSParameter(env, parameters, asyncContext); - - if (parameterCount == PARAMS_COUNT) { - if (NapiUtil::MatchValueType(env, parameters[1], napi_function)) { - NAPI_CALL(env, napi_create_reference(env, parameters[1], 1, &(asyncContext->callbackRef_))); - } - } - - napi_value result = nullptr; - - if (asyncContext->callbackRef_ == nullptr) { - NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred_, &result)); - } else { - NAPI_CALL(env, napi_get_undefined(env, &result)); - } - napi_value resourceName = nullptr; - NAPI_CALL(env, napi_create_string_utf8(env, "udpSend", NAPI_AUTO_LENGTH, &resourceName)); - - NAPI_CALL(env, - napi_create_async_work(env, nullptr, resourceName, NativeUdpSend, UdpSendCallback, (void *)asyncContext, - &(asyncContext->work_))); - napi_status resultStatus = napi_queue_async_work(env, asyncContext->work_); - if (resultStatus == napi_ok) { - NETMGR_LOGI("Udp send Async Work Successful"); - } - return result; -} - -napi_value UdpClose(napi_env env, napi_callback_info info) -{ - std::size_t parameterCount = 2; - napi_value parameters[2] = {0}; - napi_value thisVar = nullptr; - void *data = nullptr; - uint32_t flag = 0; - bool isFdExist = false; - - NAPI_CALL(env, napi_get_cb_info(env, info, ¶meterCount, parameters, &thisVar, &data)); - - Baseinfo *asyncContext = nullptr; - UDPSocket *objectInfo = nullptr; - napi_valuetype valuetype; - NAPI_CALL(env, napi_typeof(env, thisVar, &valuetype)); - - NAPI_ASSERT(env, valuetype == napi_object, "Wrong argument type for arg0. Subscribe expected."); - napi_unwrap(env, thisVar, (void **)&objectInfo); - - auto requestKey = udpSocketInstances.find(objectInfo); - if (requestKey != udpSocketInstances.end()) { - asyncContext = requestKey->second; - } else { - NETMGR_LOGE("UdpClose not find socket pointer"); - return nullptr; - } - - for (int i = 0; i < g_onInfoList.size(); i++) { - if (objectInfo->remInfo.socketfd == g_onInfoList.at(i).socketfd) { - flag = i; - isFdExist = true; - break; - } - } - if (!isFdExist) { - return nullptr; - } - - g_onInfoList[flag] = *asyncContext; - objectInfo->remInfo = *asyncContext; - - if (parameterCount == PARAMS_COUNT) { - if (NapiUtil::MatchValueType(env, parameters[1], napi_function)) { - NAPI_CALL(env, napi_create_reference(env, parameters[1], 1, &(asyncContext->callbackRef_))); - } - } - - napi_value result = nullptr; - - if (asyncContext->callbackRef_ == nullptr) { - NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred_, &result)); - } else { - NAPI_CALL(env, napi_get_undefined(env, &result)); - } - napi_value resourceName = nullptr; - NAPI_CALL(env, napi_create_string_utf8(env, "udpClose", NAPI_AUTO_LENGTH, &resourceName)); - - NAPI_CALL(env, - napi_create_async_work(env, nullptr, resourceName, NativeUdpClose, UdpCloseCallback, (void *)asyncContext, - &(asyncContext->work_))); - napi_status resultStatus = napi_queue_async_work(env, asyncContext->work_); - if (resultStatus == napi_ok) { - NETMGR_LOGI("Udp send Async Work Successful"); - } - return result; -} - -napi_value UdpGetState(napi_env env, napi_callback_info info) -{ - std::size_t parameterCount = 1; - napi_value parameters[1] = {0}; - napi_value thisVar = nullptr; - void *data = nullptr; - - NAPI_CALL(env, napi_get_cb_info(env, info, ¶meterCount, parameters, &thisVar, &data)); - - Baseinfo *asyncContext = nullptr; - UDPSocket *objectInfo = nullptr; - napi_valuetype valuetype; - - NAPI_CALL(env, napi_typeof(env, thisVar, &valuetype)); - - NAPI_ASSERT(env, valuetype == napi_object, "Wrong argument type for arg0. Subscribe expected."); - napi_unwrap(env, thisVar, (void **)&objectInfo); - - auto requestKey = udpSocketInstances.find(objectInfo); - if (requestKey != udpSocketInstances.end()) { - asyncContext = requestKey->second; - } else { - NETMGR_LOGE("UdpGetState not find socket pointer"); - return nullptr; - } - - if (parameterCount == 1) { - napi_valuetype valuetype1; - NAPI_CALL(env, napi_typeof(env, parameters[0], &valuetype1)); - if (NapiUtil::MatchValueType(env, parameters[0], napi_function)) { - NAPI_CALL(env, napi_create_reference(env, parameters[0], 1, &(asyncContext->callbackRef_))); - } - } - - napi_value result = nullptr; - - if (asyncContext->callbackRef_ == nullptr) { - NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred_, &result)); - } else { - NAPI_CALL(env, napi_get_undefined(env, &result)); - } - napi_value resourceName = nullptr; - NAPI_CALL(env, napi_create_string_utf8(env, "udpGetState", NAPI_AUTO_LENGTH, &resourceName)); - - NAPI_CALL(env, - napi_create_async_work(env, nullptr, resourceName, NativeUdpGetState, UdpGetStateCallback, (void *)asyncContext, - &(asyncContext->work_))); - napi_status resultStatus = napi_queue_async_work(env, asyncContext->work_); - if (resultStatus == napi_ok) { - NETMGR_LOGI("Udp GetState Async Work Successful"); - } - - return result; -} - -napi_value UdpSetExtraOptions(napi_env env, napi_callback_info info) -{ - std::size_t parameterCount = 2; - napi_value parameters[2] = {0}; - napi_value thisVar = nullptr; - void *data = nullptr; - uint32_t flag = 0; - bool isFdExist = false; - NAPI_CALL(env, napi_get_cb_info(env, info, ¶meterCount, parameters, &thisVar, &data)); - Baseinfo *asyncContext = nullptr; - UDPSocket *objectInfo = nullptr; - napi_valuetype valuetype; - - NAPI_CALL(env, napi_typeof(env, thisVar, &valuetype)); - NAPI_ASSERT(env, valuetype == napi_object, "Wrong argument type for arg0. Subscribe expected."); - napi_unwrap(env, thisVar, (void **)&objectInfo); - - auto requestKey = udpSocketInstances.find(objectInfo); - if (requestKey != udpSocketInstances.end()) { - asyncContext = requestKey->second; - } else { - NETMGR_LOGE("udpSocketInstances add udp socket pointer"); - return nullptr; - } - - for (int i = 0; i < g_onInfoList.size(); i++) { - if (objectInfo->remInfo.socketfd == g_onInfoList.at(i).socketfd) { - flag = i; - isFdExist = true; - asyncContext = &g_onInfoList.at(i); - break; - } - } - if (!isFdExist) { - return nullptr; - } - asyncContext->ipAddress = "255.255.255.255"; - asyncContext->broadcast = true; - - g_onInfoList[flag] = *asyncContext; - objectInfo->remInfo = *asyncContext; - - if (parameterCount == PARAMS_COUNT) { - if (NapiUtil::MatchValueType(env, parameters[1], napi_function)) { - NAPI_CALL(env, napi_create_reference(env, parameters[1], 1, &(asyncContext->callbackRef_))); - } - } - - napi_value result = nullptr; - - if (asyncContext->callbackRef_ == nullptr) { - NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred_, &result)); - } else { - NAPI_CALL(env, napi_get_undefined(env, &result)); - } - napi_value resourceName = nullptr; - NAPI_CALL(env, napi_create_string_utf8(env, "udpSetExtraOptions", NAPI_AUTO_LENGTH, &resourceName)); - - NAPI_CALL(env, - napi_create_async_work(env, nullptr, resourceName, NativeUdpSetExtraOptions, UdpSetExtraOptionsCallback, - (void *)asyncContext, &(asyncContext->work_))); - napi_status resultStatus = napi_queue_async_work(env, asyncContext->work_); - if (resultStatus == napi_ok) { - NETMGR_LOGI("Udp SetExtraOptions Async Work Successful"); - } - return result; -} - -napi_value UdpRequestConstructor(napi_env env, napi_callback_info info) -{ - std::size_t argc = 1; - napi_value argv[1]; - napi_value thisVar = nullptr; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr)); - - auto asyncContext = new Baseinfo(); - auto objectInfo = new UDPSocket(*asyncContext); - - if (udpSocketInstances.size() <= MAX_SOCKET_OBJ_COUNT) { - asyncContext->udpRequestInfo_ = objectInfo; - udpSocketInstances[objectInfo] = asyncContext; - } else { - NETMGR_LOGE("UDP object count max 100"); - return thisVar; - } - - napi_wrap(env, - thisVar, - objectInfo, - [](napi_env env, void *data, void *hint) { - UDPSocket *objectInfo = (UDPSocket *)data; - if (objectInfo) { - delete objectInfo; - objectInfo = nullptr; - } - }, - nullptr, - nullptr); - return thisVar; -} - -napi_value UdpOn(napi_env env, napi_callback_info info) -{ - std::size_t parameterCount = 2; - napi_value parameters[2] = {nullptr, nullptr}; - napi_value thisVar = nullptr; - void *data = nullptr; - - NAPI_CALL(env, napi_get_cb_info(env, info, ¶meterCount, parameters, &thisVar, &data)); - - Baseinfo *asyncContext = nullptr; - UDPSocket *objectInfo = nullptr; - napi_valuetype valuetype; - - NAPI_CALL(env, napi_typeof(env, thisVar, &valuetype)); - NAPI_ASSERT(env, valuetype == napi_object, "Wrong argument type for arg0. Subscribe expected."); - napi_unwrap(env, thisVar, (void **)&objectInfo); - - auto requestKey = udpSocketInstances.find(objectInfo); - if (requestKey != udpSocketInstances.end()) { - asyncContext = requestKey->second; - } else { - NETMGR_LOGE("udpSocketInstances add udp socket pointer"); - return nullptr; - } - - char eventTypeChars[OHOS::NetManagerStandard::EVENT_ARRAY_LENGTH] = {0}; - size_t strLen = 0; - - NAPI_CALL(env, - napi_get_value_string_utf8( - env, parameters[0], eventTypeChars, OHOS::NetManagerStandard::EVENT_ARRAY_LENGTH - 1, &strLen)); - - napi_ref callbackRef = nullptr; - - if (parameterCount == PARAMS_COUNT) { - napi_create_reference(env, parameters[1], 1, &callbackRef); - } - napi_value result = nullptr; - uint32_t eventType = GetSocketEventType(eventTypeChars); - struct UdpEventListener listener = {env, eventType, true, callbackRef, objectInfo}; - if (eventType != NONE_EVENT_TYPE) { - g_udpEventListenerList.push_back(listener); - result = thisVar; - } - - return thisVar; -} - -napi_value UdpOff(napi_env env, napi_callback_info info) -{ - std::size_t parameterCount = 2; - napi_value parameters[2] = {0}; - napi_value thisVar = nullptr; - void *data = nullptr; - - NAPI_CALL(env, napi_get_cb_info(env, info, ¶meterCount, parameters, &thisVar, &data)); - - Baseinfo *asyncContext = nullptr; - UDPSocket *objectInfo = nullptr; - napi_valuetype valuetype; - - NAPI_CALL(env, napi_typeof(env, thisVar, &valuetype)); - - NAPI_ASSERT(env, valuetype == napi_object, "Wrong argument type for arg0. Subscribe expected."); - napi_unwrap(env, thisVar, (void **)&objectInfo); - - auto requestKey = udpSocketInstances.find(objectInfo); - if (requestKey != udpSocketInstances.end()) { - asyncContext = requestKey->second; - } else { - NETMGR_LOGE("udpSocketInstances add udp socket pointer"); - return nullptr; - } - - char eventTypeChars[OHOS::NetManagerStandard::EVENT_ARRAY_LENGTH] = {0}; - size_t strLen = 0; - - NAPI_CALL(env, - napi_get_value_string_utf8( - env, parameters[0], eventTypeChars, OHOS::NetManagerStandard::EVENT_ARRAY_LENGTH - 1, &strLen)); - - napi_ref callbackRef = nullptr; - if (parameterCount == PARAMS_COUNT) { - napi_create_reference(env, parameters[1], 1, &callbackRef); - } - napi_value result = nullptr; - uint32_t eventType = GetSocketEventType(eventTypeChars); - - struct UdpEventListener listener = {env, eventType, true, callbackRef, objectInfo}; - if (eventType != NONE_EVENT_TYPE) { - napi_delete_reference(env, listener.callbackRef_); - g_udpEventListenerList.remove_if([objectInfo, eventType](UdpEventListener listener)->bool { - return (listener.udpSocket_ == objectInfo && listener.eventType_ == eventType); - }); - result = thisVar; - } - - return thisVar; -} - -static void EmitTcpEvent(TCPSocket *obj, const std::string &type, const std::string &message) -{ - int32_t eventType = GetSocketEventType(type); - for (std::list::iterator listenerIterator = g_tcpEventListenerList.begin(); - listenerIterator != g_tcpEventListenerList.end(); ++listenerIterator) { - if (listenerIterator->tcpSocket_ == obj && listenerIterator->eventType_ == eventType) { - napi_env env = listenerIterator->env_; - napi_handle_scope scope = nullptr; - napi_open_handle_scope(env, &scope); - napi_value undefine = nullptr; - napi_get_undefined(env, &undefine); - napi_ref callbackRef = listenerIterator->callbackRef_; - napi_value callbackFunc = nullptr; - napi_get_reference_value(env, callbackRef, &callbackFunc); - napi_value callbackValues[2] = {0}; - - callbackValues[0] = NapiUtil::CreateUndefined(env); - napi_value object = nullptr; - napi_create_object(env, &object); - NapiUtil::SetPropertyStringUtf8(env, object, type, message); - - callbackValues[1] = object; - napi_value callbackResult = nullptr; - napi_call_function(env, undefine, callbackFunc, PARAMS_COUNT, callbackValues, &callbackResult); - napi_close_handle_scope(env, scope); - napi_delete_reference(env, listenerIterator->callbackRef_); - break; - } - } -} - -static void NativeTcpBind(napi_env env, void *data) -{ - if (data == nullptr) { - NETMGR_LOGE("NativeTcpBind formal parameter data is null"); - return; - } - auto asyncContext = static_cast(data); - - struct sockaddr_in addr; - asyncContext->tcpSocket_->GetSocketInfo(addr, asyncContext); - - if (asyncContext->socketfd_ == INVALID_SOCKET && asyncContext->tcpSocket_ != nullptr) { - if (asyncContext->family == IPV6) { - asyncContext->socketfd_ = asyncContext->tcpSocket_->TcpSocket(AF_INET6, SOCK_STREAM, 0); - } else { - asyncContext->socketfd_ = asyncContext->tcpSocket_->TcpSocket(AF_INET, SOCK_STREAM, 0); - } - if (asyncContext->socketfd_ < 0) { - return; - } - } - - if (!asyncContext->isBound && asyncContext->isClose && !asyncContext->isConnected) { - asyncContext->errorCode_ = asyncContext->tcpSocket_->TcpBind(asyncContext->socketfd_, - (struct sockaddr *)&addr, sizeof(struct sockaddr)); - } - if (asyncContext->errorCode_ >= 0) { - asyncContext->isBound = true; - asyncContext->resolved_ = true; - asyncContext->errorString_.clear(); - } else { - asyncContext->errorString_ = strerror(errno); - std::string error = asyncContext->errorString_; - EmitTcpEvent(asyncContext->tcpSocket_, "error", error); - } -} - -static void TcpBindCallback(napi_env env, napi_status status, void *data) -{ - if (data == nullptr) { - NETMGR_LOGE("TcpBindCallback data parameter address is nullptr"); - return; - } - auto asyncContext = static_cast(data); - napi_value callbackValue = nullptr; - - if (asyncContext->resolved_) { - napi_create_object(env, &callbackValue); - NapiUtil::SetPropertyInt32(env, callbackValue, "errorCode", asyncContext->errorCode_); - } else { - callbackValue = NapiUtil::CreateErrorMessage(env, asyncContext->errorString_); - } - if (asyncContext->callbackRef_ != nullptr) { - napi_value callbackFunc = nullptr; - napi_get_reference_value(env, asyncContext->callbackRef_, &callbackFunc); - napi_value callbackValues[] = {nullptr, nullptr}; - callbackValues[0] = asyncContext->resolved_ ? NapiUtil::CreateUndefined(env) : callbackValue; - callbackValues[1] = asyncContext->resolved_ ? callbackValue : NapiUtil::CreateUndefined(env); - napi_value undefined = nullptr; - napi_value callback = nullptr; - napi_value result = nullptr; - NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); - NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, asyncContext->callbackRef_, &callback)); - NAPI_CALL_RETURN_VOID( - env, napi_call_function(env, undefined, callback, std::size(callbackValues), callbackValues, &result)); - NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, asyncContext->callbackRef_)); - } else if (asyncContext->deferred_ != nullptr) { - if (asyncContext->resolved_) { - napi_resolve_deferred(env, asyncContext->deferred_, callbackValue); - } else { - napi_reject_deferred(env, asyncContext->deferred_, callbackValue); - } - } - - napi_delete_async_work(env, asyncContext->work_); -} - -static void NativeTcpConnect(napi_env env, void *data) -{ - if (data == nullptr) { - NETMGR_LOGE("NativeTcpConnect formal parameter data is null"); - return; - } - auto asyncContext = static_cast(data); - - struct sockaddr_in addr; - asyncContext->tcpSocket_->GetSocketInfo(addr, asyncContext); - - if (asyncContext->socketfd_ == INVALID_SOCKET && asyncContext->tcpSocket_ != nullptr) { - if (asyncContext->family == IPV6) { - asyncContext->socketfd_ = asyncContext->tcpSocket_->TcpSocket(AF_INET6, SOCK_STREAM, 0); - } else { - asyncContext->socketfd_ = asyncContext->tcpSocket_->TcpSocket(AF_INET, SOCK_STREAM, 0); - } - if (asyncContext->socketfd_ < 0) { - return; - } - } - - if (!asyncContext->isBound && asyncContext->isClose && !asyncContext->isConnected) { - asyncContext->errorCode_ = asyncContext->tcpSocket_->TcpConnect(asyncContext->socketfd_, - (struct sockaddr *)&addr, sizeof(struct sockaddr)); - } - if (asyncContext->errorCode_ >= 0) { - asyncContext->isConnected = true; - asyncContext->isClose = false; - std::string connect("connect"); - EmitTcpEvent(asyncContext->tcpSocket_, "connect", connect); - } else { - asyncContext->errorString_ = strerror(errno); - std::string error = asyncContext->errorString_; - EmitTcpEvent(asyncContext->tcpSocket_, "error", error); - } -} - -static void TcpConnectCallback(napi_env env, napi_status status, void *data) -{ - if (data == nullptr) { - NETMGR_LOGE("TcpConnectCallback data parameter address is nullptr"); - return; - } - auto asyncContext = static_cast(data); - napi_value callbackValue = nullptr; - - if (asyncContext->resolved_) { - napi_create_object(env, &callbackValue); - NapiUtil::SetPropertyInt32(env, callbackValue, "errorCode", asyncContext->errorCode_); - } else { - callbackValue = NapiUtil::CreateErrorMessage(env, asyncContext->errorString_); - } - if (asyncContext->callbackRef_ != nullptr) { - napi_value callbackFunc = nullptr; - napi_get_reference_value(env, asyncContext->callbackRef_, &callbackFunc); - napi_value callbackValues[] = {nullptr, nullptr}; - callbackValues[0] = asyncContext->resolved_ ? NapiUtil::CreateUndefined(env) : callbackValue; - callbackValues[1] = asyncContext->resolved_ ? callbackValue : NapiUtil::CreateUndefined(env); - napi_value undefined = nullptr; - napi_value callback = nullptr; - napi_value result = nullptr; - NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); - NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, asyncContext->callbackRef_, &callback)); - NAPI_CALL_RETURN_VOID( - env, napi_call_function(env, undefined, callback, std::size(callbackValues), callbackValues, &result)); - NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, asyncContext->callbackRef_)); - } else if (asyncContext->deferred_ != nullptr) { - if (asyncContext->resolved_) { - napi_resolve_deferred(env, asyncContext->deferred_, callbackValue); - } else { - napi_reject_deferred(env, asyncContext->deferred_, callbackValue); - } - } - - napi_delete_async_work(env, asyncContext->work_); -} - -static void NativeTcpSend(napi_env env, void *data) -{ - if (data == nullptr) { - NETMGR_LOGE("NativeUdpBind formal parameter data is null"); - return; - } - auto asyncContext = static_cast(data); - - struct sockaddr_in addr; - asyncContext->tcpSocket_->GetSocketInfo(addr, asyncContext); - - if (!asyncContext->isClose) { - asyncContext->errorCode_ = asyncContext->tcpSocket_->TcpSend(asyncContext->socketfd_, - asyncContext->data.c_str(), asyncContext->data.size(), 0); - std::string message("message"); - EmitTcpEvent(asyncContext->tcpSocket_, "message", message); - } else { - asyncContext->errorString_ = strerror(errno); - std::string error = asyncContext->errorString_; - EmitTcpEvent(asyncContext->tcpSocket_, "error", error); - } -} - -static void TcpSendCallback(napi_env env, napi_status status, void *data) -{ - if (data == nullptr) { - NETMGR_LOGE("TcpSendCallback data parameter address is nullptr"); - return; - } - auto asyncContext = static_cast(data); - napi_value callbackValue = nullptr; - - if (asyncContext->resolved_) { - napi_create_object(env, &callbackValue); - NapiUtil::SetPropertyInt32(env, callbackValue, "errorCode", asyncContext->errorCode_); - } else { - callbackValue = NapiUtil::CreateErrorMessage(env, asyncContext->errorString_); - } - if (asyncContext->callbackRef_ != nullptr) { - napi_value callbackFunc = nullptr; - napi_get_reference_value(env, asyncContext->callbackRef_, &callbackFunc); - napi_value callbackValues[] = {nullptr, nullptr}; - callbackValues[0] = asyncContext->resolved_ ? NapiUtil::CreateUndefined(env) : callbackValue; - callbackValues[1] = asyncContext->resolved_ ? callbackValue : NapiUtil::CreateUndefined(env); - napi_value undefined = nullptr; - napi_value callback = nullptr; - napi_value result = nullptr; - NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); - NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, asyncContext->callbackRef_, &callback)); - NAPI_CALL_RETURN_VOID( - env, napi_call_function(env, undefined, callback, std::size(callbackValues), callbackValues, &result)); - NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, asyncContext->callbackRef_)); - } else if (asyncContext->deferred_ != nullptr) { - if (asyncContext->resolved_) { - napi_resolve_deferred(env, asyncContext->deferred_, callbackValue); - } else { - napi_reject_deferred(env, asyncContext->deferred_, callbackValue); - } - } - - napi_delete_async_work(env, asyncContext->work_); -} - -static void NativeTcpClose(napi_env env, void *data) -{ - if (data == nullptr) { - NETMGR_LOGE("NativeTcpClose formal parameter data is null"); - return; - } - auto asyncContext = static_cast(data); - - if (!asyncContext->isClose) { - asyncContext->errorCode_ = asyncContext->tcpSocket_->TcpClose(asyncContext->socketfd_); - } - - if (asyncContext->errorCode_ >= 0) { - std::string close("close"); - EmitTcpEvent(asyncContext->tcpSocket_, "close", close); - } else { - std::string error("error"); - EmitTcpEvent(asyncContext->tcpSocket_, "error", error); - } -} - -static void TcpCloseCallback(napi_env env, napi_status status, void *data) -{ - if (data == nullptr) { - NETMGR_LOGE("TcpCloseCallback data parameter address is nullptr"); - return; - } - auto asyncContext = static_cast(data); - napi_value callbackValue = nullptr; - - if (asyncContext->resolved_) { - napi_create_object(env, &callbackValue); - NapiUtil::SetPropertyInt32(env, callbackValue, "errorCode", asyncContext->errorCode_); - } else { - callbackValue = NapiUtil::CreateErrorMessage(env, "tcp socket close failed"); - } - if (asyncContext->callbackRef_ != nullptr) { - napi_value callbackFunc = nullptr; - napi_get_reference_value(env, asyncContext->callbackRef_, &callbackFunc); - napi_value callbackValues[] = {nullptr, nullptr}; - callbackValues[0] = asyncContext->resolved_ ? NapiUtil::CreateUndefined(env) : callbackValue; - callbackValues[1] = asyncContext->resolved_ ? callbackValue : NapiUtil::CreateUndefined(env); - napi_value undefined = nullptr; - napi_value callback = nullptr; - napi_value result = nullptr; - NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); - NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, asyncContext->callbackRef_, &callback)); - NAPI_CALL_RETURN_VOID( - env, napi_call_function(env, undefined, callback, std::size(callbackValues), callbackValues, &result)); - NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, asyncContext->callbackRef_)); - } else if (asyncContext->deferred_ != nullptr) { - if (asyncContext->resolved_) { - napi_resolve_deferred(env, asyncContext->deferred_, callbackValue); - } else { - napi_reject_deferred(env, asyncContext->deferred_, callbackValue); - } - } - - napi_delete_async_work(env, asyncContext->work_); -} - -static void NativeTcpGetRemoteAddress(napi_env env, void *data) -{ - if (data == nullptr) { - NETMGR_LOGE("NativeTcpGetState formal parameter data is null"); - return; - } - auto asyncContext = static_cast(data); - asyncContext->resolved_ = true; - asyncContext->errorString_.clear(); -} - -static void TcpGetRemoteAddressCallback(napi_env env, napi_status status, void *data) -{ - if (data == nullptr) { - NETMGR_LOGE("TcpGetRemoteAddressCallback data parameter address is nullptr"); - return; - } - auto asyncContext = static_cast(data); - napi_value callbackValue = nullptr; - - if (asyncContext->resolved_) { - napi_create_object(env, &callbackValue); - NapiUtil::SetPropertyStringUtf8(env, callbackValue, "ipAddress", asyncContext->ipAddress); - NapiUtil::SetPropertyInt32(env, callbackValue, "family", asyncContext->family); - NapiUtil::SetPropertyInt32(env, callbackValue, "port", asyncContext->port); - } else { - callbackValue = NapiUtil::CreateErrorMessage(env, "tcp socket getRemoteAddress failed"); - } - if (asyncContext->callbackRef_ != nullptr) { - napi_value callbackFunc = nullptr; - napi_get_reference_value(env, asyncContext->callbackRef_, &callbackFunc); - napi_value callbackValues[] = {nullptr, nullptr}; - callbackValues[0] = asyncContext->resolved_ ? NapiUtil::CreateUndefined(env) : callbackValue; - callbackValues[1] = asyncContext->resolved_ ? callbackValue : NapiUtil::CreateUndefined(env); - napi_value undefined = nullptr; - napi_value callback = nullptr; - napi_value result = nullptr; - NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); - NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, asyncContext->callbackRef_, &callback)); - NAPI_CALL_RETURN_VOID( - env, napi_call_function(env, undefined, callback, std::size(callbackValues), callbackValues, &result)); - NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, asyncContext->callbackRef_)); - } else if (asyncContext->deferred_ != nullptr) { - if (asyncContext->resolved_) { - napi_resolve_deferred(env, asyncContext->deferred_, callbackValue); - } else { - napi_reject_deferred(env, asyncContext->deferred_, callbackValue); - } - } - - napi_delete_async_work(env, asyncContext->work_); -} - -static void NativeTcpGetState(napi_env env, void *data) -{ - if (data == nullptr) { - NETMGR_LOGE("NativeTcpGetState formal parameter data is null"); - return; - } - auto asyncContext = static_cast(data); - asyncContext->resolved_ = true; - asyncContext->errorString_.clear(); -} - -static void TcpGetStateCallback(napi_env env, napi_status status, void *data) -{ - if (data == nullptr) { - NETMGR_LOGE("TcpGetStateCallback data parameter address is nullptr"); - return; - } - auto asyncContext = static_cast(data); - napi_value callbackValue = nullptr; - - if (asyncContext->resolved_) { - napi_create_object(env, &callbackValue); - NapiUtil::SetPropertyInt32(env, callbackValue, "isBound", asyncContext->isBound); - NapiUtil::SetPropertyInt32(env, callbackValue, "isClose", asyncContext->isClose); - NapiUtil::SetPropertyInt32(env, callbackValue, "isConnected", asyncContext->isConnected); - } else { - callbackValue = NapiUtil::CreateErrorMessage(env, "tcp socket getState failed"); - } - if (asyncContext->callbackRef_ != nullptr) { - napi_value callbackFunc = nullptr; - napi_get_reference_value(env, asyncContext->callbackRef_, &callbackFunc); - napi_value callbackValues[] = {nullptr, nullptr}; - callbackValues[0] = asyncContext->resolved_ ? NapiUtil::CreateUndefined(env) : callbackValue; - callbackValues[1] = asyncContext->resolved_ ? callbackValue : NapiUtil::CreateUndefined(env); - napi_value undefined = nullptr; - napi_value callback = nullptr; - napi_value result = nullptr; - NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); - NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, asyncContext->callbackRef_, &callback)); - NAPI_CALL_RETURN_VOID( - env, napi_call_function(env, undefined, callback, std::size(callbackValues), callbackValues, &result)); - NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, asyncContext->callbackRef_)); - } else if (asyncContext->deferred_ != nullptr) { - if (asyncContext->resolved_) { - napi_resolve_deferred(env, asyncContext->deferred_, callbackValue); - } else { - napi_reject_deferred(env, asyncContext->deferred_, callbackValue); - } - } - - napi_delete_async_work(env, asyncContext->work_); -} - -static void NativeTcpSetExtraOptions(napi_env env, void *data) -{ - if (data == nullptr) { - NETMGR_LOGE("NativeSetExtraOptionsSend formal parameter data is null"); - return; - } - auto asyncContext = static_cast(data); - - struct sockaddr_in addr; - asyncContext->tcpSocket_->GetSocketInfo(addr, asyncContext); - - if (asyncContext->socketfd_ == INVALID_SOCKET && asyncContext->tcpSocket_ != nullptr) { - if (asyncContext->family == IPV6) { - asyncContext->socketfd_ = asyncContext->tcpSocket_->TcpSocket(AF_INET6, SOCK_STREAM, 0); - } else { - asyncContext->socketfd_ = asyncContext->tcpSocket_->TcpSocket(AF_INET, SOCK_STREAM, 0); - } - if (asyncContext->socketfd_ < 0) { - return; - } - } - - bool keepAlive = asyncContext->tcpExtraOptions_.GetKeepAlive(); - if (keepAlive) { - asyncContext->errorCode_ = asyncContext->tcpSocket_->TcpSetSockopt(asyncContext->socketfd_, - SOL_SOCKET, SO_KEEPALIVE, (void *) &keepAlive, sizeof (keepAlive)); - } - - bool OOBInline = asyncContext->tcpExtraOptions_.GetOOBInline(); - if (OOBInline) { - asyncContext->errorCode_ = asyncContext->tcpSocket_->TcpSetSockopt(asyncContext->socketfd_, - SOL_SOCKET, SO_OOBINLINE, (void *) &OOBInline, sizeof (OOBInline)); - } - - bool TCPNoDelay = asyncContext->tcpExtraOptions_.GetTCPNoDelay(); - if (TCPNoDelay) { - asyncContext->errorCode_ = asyncContext->tcpSocket_->TcpSetSockopt(asyncContext->socketfd_, - IPPROTO_TCP, TCP_NODELAY, (void *) &TCPNoDelay, sizeof (TCPNoDelay)); - } - - bool on = asyncContext->tcpExtraOptions_.GetSocketLingerOn(); - int32_t intLinger = asyncContext->tcpExtraOptions_.GetSocketLingerLinger(); - if (on) { - struct linger linger; - linger.l_onoff = on; - linger.l_linger = intLinger; - asyncContext->errorCode_ = asyncContext->tcpSocket_->TcpSetSockopt(asyncContext->socketfd_, - SOL_SOCKET, SO_LINGER, (void *) &linger, sizeof (linger)); - } - - if (asyncContext->errorCode_ < 0) { - std::string error = strerror(errno); - EmitTcpEvent(asyncContext->tcpSocket_, "error", error); - } else { - asyncContext->errorString_.clear(); - asyncContext->resolved_ = true; - std::string message("message"); - EmitTcpEvent(asyncContext->tcpSocket_, "message", message); - } -} - -static void TcpSetExtraOptionsCallback(napi_env env, napi_status status, void *data) -{ - if (data == nullptr) { - NETMGR_LOGE("TcpSetExtraOptionsCallback data parameter address is nullptr"); - return; - } - auto asyncContext = static_cast(data); - napi_value callbackValue = nullptr; - - if (asyncContext->resolved_) { - napi_create_object(env, &callbackValue); - NapiUtil::SetPropertyInt32(env, callbackValue, "errorCode", asyncContext->errorCode_); - } else { - callbackValue = NapiUtil::CreateErrorMessage(env, "tcp socket SetExtraOptions failed"); - } - if (asyncContext->callbackRef_ != nullptr) { - napi_value callbackFunc = nullptr; - napi_get_reference_value(env, asyncContext->callbackRef_, &callbackFunc); - napi_value callbackValues[] = {nullptr, nullptr}; - callbackValues[0] = asyncContext->resolved_ ? NapiUtil::CreateUndefined(env) : callbackValue; - callbackValues[1] = asyncContext->resolved_ ? callbackValue : NapiUtil::CreateUndefined(env); - napi_value undefined = nullptr; - napi_value callback = nullptr; - napi_value result = nullptr; - NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); - NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, asyncContext->callbackRef_, &callback)); - NAPI_CALL_RETURN_VOID( - env, napi_call_function(env, undefined, callback, std::size(callbackValues), callbackValues, &result)); - NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, asyncContext->callbackRef_)); - } else if (asyncContext->deferred_ != nullptr) { - if (asyncContext->resolved_) { - napi_resolve_deferred(env, asyncContext->deferred_, callbackValue); - } else { - napi_reject_deferred(env, asyncContext->deferred_, callbackValue); - } - } - - napi_delete_async_work(env, asyncContext->work_); -} - -napi_value CreateTCPSocket(napi_env env, napi_callback_info info) -{ - napi_value thisVar = nullptr; - std::size_t argc = 2; - napi_value args[2] = { nullptr }; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &thisVar, nullptr)); - - napi_value result = nullptr; - napi_value argvArray[] = {nullptr}; - napi_new_instance(env, g_TcpSocketConstructorJS, 0, argvArray, &result); - - return result; -} - -napi_value TcpBind(napi_env env, napi_callback_info info) -{ - std::size_t parameterCount = 2; - napi_value parameters[2] = {0}; - napi_value thisVar = nullptr; - void *data = nullptr; - - NAPI_CALL(env, napi_get_cb_info(env, info, ¶meterCount, parameters, &thisVar, &data)); - - TcpBaseContext *asyncContext = nullptr; - TCPSocket *objectInfo = nullptr; - napi_valuetype valuetype; - - NAPI_CALL(env, napi_typeof(env, thisVar, &valuetype)); - NAPI_ASSERT(env, valuetype == napi_object, "Wrong argument type for arg0. Subscribe expected."); - napi_unwrap(env, thisVar, (void **)&objectInfo); - - auto requestKey = tcpSocketInstances.find(objectInfo); - if (requestKey != tcpSocketInstances.end()) { - asyncContext = requestKey->second; - } else { - NETMGR_LOGE("tcpSocketInstances add udp socket pointer"); - return nullptr; - } - - objectInfo->GetJSParameter(env, parameters, asyncContext); - - if (parameterCount == PARAMS_COUNT) { - if (NapiUtil::MatchValueType(env, parameters[1], napi_function)) { - NAPI_CALL(env, napi_create_reference(env, parameters[1], 1, &(asyncContext->callbackRef_))); - } - } - - napi_value result = nullptr; - - if (asyncContext->callbackRef_ == nullptr) { - NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred_, &result)); - } else { - NAPI_CALL(env, napi_get_undefined(env, &result)); - } - napi_value resourceName = nullptr; - NAPI_CALL(env, napi_create_string_utf8(env, "tcpBind", NAPI_AUTO_LENGTH, &resourceName)); - - NAPI_CALL(env, - napi_create_async_work(env, nullptr, resourceName, NativeTcpBind, TcpBindCallback, (void *)asyncContext, - &(asyncContext->work_))); - napi_status resultStatus = napi_queue_async_work(env, asyncContext->work_); - if (resultStatus == napi_ok) { - NETMGR_LOGI("Tcp bind Async Work Successful"); - } - - return result; -} - -napi_value TcpConnect(napi_env env, napi_callback_info info) -{ - std::size_t parameterCount = 2; - napi_value parameters[2] = {0}; - napi_value thisVar = nullptr; - void *data = nullptr; - - NAPI_CALL(env, napi_get_cb_info(env, info, ¶meterCount, parameters, &thisVar, &data)); - - TcpBaseContext *asyncContext = nullptr; - TCPSocket *objectInfo = nullptr; - napi_valuetype valuetype; - - NAPI_CALL(env, napi_typeof(env, thisVar, &valuetype)); - NAPI_ASSERT(env, valuetype == napi_object, "Wrong argument type for arg0. Subscribe expected."); - napi_unwrap(env, thisVar, (void **)&objectInfo); - - auto requestKey = tcpSocketInstances.find(objectInfo); - if (requestKey != tcpSocketInstances.end()) { - asyncContext = requestKey->second; - } else { - NETMGR_LOGE("tcpSocketInstances add udp socket pointer"); - return nullptr; - } - - objectInfo->GetJSParameter(env, parameters, asyncContext); - - if (parameterCount == PARAMS_COUNT) { - if (NapiUtil::MatchValueType(env, parameters[1], napi_function)) { - NAPI_CALL(env, napi_create_reference(env, parameters[1], 1, &(asyncContext->callbackRef_))); - } - } - - napi_value result = nullptr; - - if (asyncContext->callbackRef_ == nullptr) { - NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred_, &result)); - } else { - NAPI_CALL(env, napi_get_undefined(env, &result)); - } - napi_value resourceName = nullptr; - NAPI_CALL(env, napi_create_string_utf8(env, "tcpConnect", NAPI_AUTO_LENGTH, &resourceName)); - - NAPI_CALL(env, - napi_create_async_work(env, nullptr, resourceName, NativeTcpConnect, TcpConnectCallback, (void *)asyncContext, - &(asyncContext->work_))); - napi_status resultStatus = napi_queue_async_work(env, asyncContext->work_); - if (resultStatus == napi_ok) { - NETMGR_LOGI("Tcp connect Async Work Successful"); - } - - return result; -} - -napi_value TcpSend(napi_env env, napi_callback_info info) -{ - std::size_t parameterCount = 2; - napi_value parameters[2] = {0}; - napi_value thisVar = nullptr; - void *data = nullptr; - - NAPI_CALL(env, napi_get_cb_info(env, info, ¶meterCount, parameters, &thisVar, &data)); - - TcpBaseContext *asyncContext = nullptr; - TCPSocket *objectInfo = nullptr; - napi_valuetype valuetype; - - NAPI_CALL(env, napi_typeof(env, thisVar, &valuetype)); - NAPI_ASSERT(env, valuetype == napi_object, "Wrong argument type for arg0. Subscribe expected."); - napi_unwrap(env, thisVar, (void **)&objectInfo); - - auto requestKey = tcpSocketInstances.find(objectInfo); - if (requestKey != tcpSocketInstances.end()) { - asyncContext = requestKey->second; - } else { - NETMGR_LOGE("tcpSocketInstances add udp socket pointer"); - return nullptr; - } - - objectInfo->GetJSParameter(env, parameters, asyncContext); - - if (parameterCount == PARAMS_COUNT) { - if (NapiUtil::MatchValueType(env, parameters[1], napi_function)) { - NAPI_CALL(env, napi_create_reference(env, parameters[1], 1, &(asyncContext->callbackRef_))); - } - } - - napi_value result = nullptr; - - if (asyncContext->callbackRef_ == nullptr) { - NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred_, &result)); - } else { - NAPI_CALL(env, napi_get_undefined(env, &result)); - } - napi_value resourceName = nullptr; - NAPI_CALL(env, napi_create_string_utf8(env, "tcpBind", NAPI_AUTO_LENGTH, &resourceName)); - - NAPI_CALL(env, - napi_create_async_work(env, nullptr, resourceName, NativeTcpSend, TcpSendCallback, (void *)asyncContext, - &(asyncContext->work_))); - napi_status resultStatus = napi_queue_async_work(env, asyncContext->work_); - if (resultStatus == napi_ok) { - NETMGR_LOGI("Udp bind Async Work Successful"); - } - - return result; -} - -napi_value TcpClose(napi_env env, napi_callback_info info) -{ - std::size_t parameterCount = 2; - napi_value parameters[2] = {0}; - napi_value thisVar = nullptr; - void *data = nullptr; - - NAPI_CALL(env, napi_get_cb_info(env, info, ¶meterCount, parameters, &thisVar, &data)); - - TcpBaseContext *asyncContext = nullptr; - TCPSocket *objectInfo = nullptr; - napi_valuetype valuetype; - - NAPI_CALL(env, napi_typeof(env, thisVar, &valuetype)); - NAPI_ASSERT(env, valuetype == napi_object, "Wrong argument type for arg0. Subscribe expected."); - napi_unwrap(env, thisVar, (void **)&objectInfo); - - auto requestKey = tcpSocketInstances.find(objectInfo); - if (requestKey != tcpSocketInstances.end()) { - asyncContext = requestKey->second; - } else { - NETMGR_LOGE("tcpClose not find socket pointer"); - return nullptr; - } - - objectInfo->GetJSParameter(env, parameters, asyncContext); - - struct sockaddr_in addr; - objectInfo->GetSocketInfo(addr, asyncContext); - - if (parameterCount == PARAMS_COUNT) { - if (NapiUtil::MatchValueType(env, parameters[1], napi_function)) { - NAPI_CALL(env, napi_create_reference(env, parameters[1], 1, &(asyncContext->callbackRef_))); - } - } - - napi_value result = nullptr; - - if (asyncContext->callbackRef_ == nullptr) { - NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred_, &result)); - } else { - NAPI_CALL(env, napi_get_undefined(env, &result)); - } - napi_value resourceName = nullptr; - NAPI_CALL(env, napi_create_string_utf8(env, "tcpClose", NAPI_AUTO_LENGTH, &resourceName)); - - NAPI_CALL(env, - napi_create_async_work(env, nullptr, resourceName, NativeTcpClose, TcpCloseCallback, (void *)asyncContext, - &(asyncContext->work_))); - napi_status resultStatus = napi_queue_async_work(env, asyncContext->work_); - if (resultStatus == napi_ok) { - NETMGR_LOGI("Udp close Async Work Successful"); - } - - return result; -} - -napi_value TcpGetRemoteAddress(napi_env env, napi_callback_info info) -{ - std::size_t parameterCount = 2; - napi_value parameters[2] = {0}; - napi_value thisVar = nullptr; - void *data = nullptr; - - NAPI_CALL(env, napi_get_cb_info(env, info, ¶meterCount, parameters, &thisVar, &data)); - - TcpBaseContext *asyncContext = nullptr; - TCPSocket *objectInfo = nullptr; - napi_valuetype valuetype; - - NAPI_CALL(env, napi_typeof(env, thisVar, &valuetype)); - NAPI_ASSERT(env, valuetype == napi_object, "Wrong argument type for arg0. Subscribe expected."); - napi_unwrap(env, thisVar, (void **)&objectInfo); - - auto requestKey = tcpSocketInstances.find(objectInfo); - if (requestKey != tcpSocketInstances.end()) { - asyncContext = requestKey->second; - } else { - NETMGR_LOGE("tcpGetRemoteAddress not find socket pointer"); - return nullptr; - } - - objectInfo->GetJSParameter(env, parameters, asyncContext); - - if (parameterCount == PARAMS_COUNT) { - if (NapiUtil::MatchValueType(env, parameters[1], napi_function)) { - NAPI_CALL(env, napi_create_reference(env, parameters[1], 1, &(asyncContext->callbackRef_))); - } - } - - napi_value result = nullptr; - - if (asyncContext->callbackRef_ == nullptr) { - NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred_, &result)); - } else { - NAPI_CALL(env, napi_get_undefined(env, &result)); - } - napi_value resourceName = nullptr; - NAPI_CALL(env, napi_create_string_utf8(env, "tcpGetRemoteAddress", NAPI_AUTO_LENGTH, &resourceName)); - - NAPI_CALL(env, - napi_create_async_work(env, nullptr, resourceName, NativeTcpGetRemoteAddress, TcpGetRemoteAddressCallback, - (void *)asyncContext, &(asyncContext->work_))); - napi_status resultStatus = napi_queue_async_work(env, asyncContext->work_); - if (resultStatus == napi_ok) { - NETMGR_LOGI("GetRemoteAddress Async Work Successful"); - } - - return result; -} - -napi_value TcpGetState(napi_env env, napi_callback_info info) -{ - std::size_t parameterCount = 2; - napi_value parameters[2] = {0}; - napi_value thisVar = nullptr; - void *data = nullptr; - - NAPI_CALL(env, napi_get_cb_info(env, info, ¶meterCount, parameters, &thisVar, &data)); - - TcpBaseContext *asyncContext = nullptr; - TCPSocket *objectInfo = nullptr; - napi_valuetype valuetype; - - NAPI_CALL(env, napi_typeof(env, thisVar, &valuetype)); - NAPI_ASSERT(env, valuetype == napi_object, "Wrong argument type for arg0. Subscribe expected."); - napi_unwrap(env, thisVar, (void **)&objectInfo); - - auto requestKey = tcpSocketInstances.find(objectInfo); - if (requestKey != tcpSocketInstances.end()) { - asyncContext = requestKey->second; - } else { - NETMGR_LOGE("tcpGetState not find socket pointer"); - return nullptr; - } - - objectInfo->GetJSParameter(env, parameters, asyncContext); - - if (parameterCount == PARAMS_COUNT) { - if (NapiUtil::MatchValueType(env, parameters[1], napi_function)) { - NAPI_CALL(env, napi_create_reference(env, parameters[1], 1, &(asyncContext->callbackRef_))); - } - } - - napi_value result = nullptr; - - if (asyncContext->callbackRef_ == nullptr) { - NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred_, &result)); - } else { - NAPI_CALL(env, napi_get_undefined(env, &result)); - } - napi_value resourceName = nullptr; - NAPI_CALL(env, napi_create_string_utf8(env, "tcpGetState", NAPI_AUTO_LENGTH, &resourceName)); - - NAPI_CALL(env, - napi_create_async_work(env, nullptr, resourceName, NativeTcpGetState, TcpGetStateCallback, (void *)asyncContext, - &(asyncContext->work_))); - napi_status resultStatus = napi_queue_async_work(env, asyncContext->work_); - if (resultStatus == napi_ok) { - NETMGR_LOGI("tcpGetState Async Work Successful"); - } - - return result; -} - -napi_value TcpSetExtraOptions(napi_env env, napi_callback_info info) -{ - std::size_t parameterCount = 2; - napi_value parameters[2] = {0}; - napi_value thisVar = nullptr; - void *data = nullptr; - - NAPI_CALL(env, napi_get_cb_info(env, info, ¶meterCount, parameters, &thisVar, &data)); - - TcpBaseContext *asyncContext = nullptr; - TCPSocket *objectInfo = nullptr; - napi_valuetype valuetype; - - NAPI_CALL(env, napi_typeof(env, thisVar, &valuetype)); - NAPI_ASSERT(env, valuetype == napi_object, "Wrong argument type for arg0. Subscribe expected."); - napi_unwrap(env, thisVar, (void **)&objectInfo); - - auto requestKey = tcpSocketInstances.find(objectInfo); - if (requestKey != tcpSocketInstances.end()) { - asyncContext = requestKey->second; - } else { - NETMGR_LOGE("tcpSetExtraOptions not find socket pointer"); - return nullptr; - } - - asyncContext->ipAddress = "255.255.255.255"; - asyncContext->broadcast = true; - - objectInfo->GetJSParameter(env, parameters, asyncContext); - - objectInfo->GetExOpGetJSParameter(env, parameters, asyncContext); - - if (parameterCount == PARAMS_COUNT) { - if (NapiUtil::MatchValueType(env, parameters[1], napi_function)) { - NAPI_CALL(env, napi_create_reference(env, parameters[1], 1, &(asyncContext->callbackRef_))); - } - } - - napi_value result = nullptr; - - if (asyncContext->callbackRef_ == nullptr) { - NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred_, &result)); - } else { - NAPI_CALL(env, napi_get_undefined(env, &result)); - } - napi_value resourceName = nullptr; - NAPI_CALL(env, napi_create_string_utf8(env, "tcpSetExtraOptions", NAPI_AUTO_LENGTH, &resourceName)); - - NAPI_CALL(env, - napi_create_async_work(env, nullptr, resourceName, NativeTcpSetExtraOptions, TcpSetExtraOptionsCallback, - (void *)asyncContext, &(asyncContext->work_))); - napi_status resultStatus = napi_queue_async_work(env, asyncContext->work_); - if (resultStatus == napi_ok) { - NETMGR_LOGI("tcpSetExtraOptions Async Work Successful"); - } - return result; -} - -napi_value TcpOn(napi_env env, napi_callback_info info) -{ - std::size_t parameterCount = 2; - napi_value parameters[2] = {0}; - napi_value thisVar = nullptr; - void *data = nullptr; - - NAPI_CALL(env, napi_get_cb_info(env, info, ¶meterCount, parameters, &thisVar, &data)); - - TcpBaseContext *asyncContext = nullptr; - TCPSocket *objectInfo = nullptr; - napi_valuetype valuetype; - - NAPI_CALL(env, napi_typeof(env, thisVar, &valuetype)); - NAPI_ASSERT(env, valuetype == napi_object, "Wrong argument type for arg0. Subscribe expected."); - napi_unwrap(env, thisVar, (void **)&objectInfo); - - auto requestKey = tcpSocketInstances.find(objectInfo); - if (requestKey != tcpSocketInstances.end()) { - asyncContext = requestKey->second; - } else { - NETMGR_LOGE("tcpSocketInstances add udp socket pointer"); - return nullptr; - } - - char eventTypeChars[OHOS::NetManagerStandard::EVENT_ARRAY_LENGTH] = { 0 }; - size_t strLen = 0; - - NAPI_CALL(env, - napi_get_value_string_utf8( - env, parameters[0], eventTypeChars, OHOS::NetManagerStandard::EVENT_ARRAY_LENGTH - 1, &strLen)); - - napi_ref callbackRef = nullptr; - - if (parameterCount == PARAMS_COUNT) { - napi_create_reference(env, parameters[1], 1, &callbackRef); - } - napi_value result = nullptr; - uint32_t eventType = GetSocketEventType(eventTypeChars); - - struct TcpEventListener listener = {env, eventType, true, callbackRef, objectInfo}; - if (eventType != NONE_EVENT_TYPE) { - g_tcpEventListenerList.push_back(listener); - result = thisVar; - } - - return thisVar; -} - -napi_value TcpOff(napi_env env, napi_callback_info info) -{ - std::size_t parameterCount = 2; - napi_value parameters[2] = {0}; - napi_value thisVar = nullptr; - void *data = nullptr; - - NAPI_CALL(env, napi_get_cb_info(env, info, ¶meterCount, parameters, &thisVar, &data)); - - TcpBaseContext *asyncContext = nullptr; - TCPSocket *objectInfo = nullptr; - napi_valuetype valuetype; - - NAPI_CALL(env, napi_typeof(env, thisVar, &valuetype)); - NAPI_ASSERT(env, valuetype == napi_object, "Wrong argument type for arg0. Subscribe expected."); - napi_unwrap(env, thisVar, (void **)&objectInfo); - - auto requestKey = tcpSocketInstances.find(objectInfo); - if (requestKey != tcpSocketInstances.end()) { - asyncContext = requestKey->second; - } else { - NETMGR_LOGE("tcpOff not find socket pointer"); - return nullptr; - } - - char eventTypeChars[OHOS::NetManagerStandard::EVENT_ARRAY_LENGTH] = {0}; - size_t strLen = 0; - - NAPI_CALL(env, - napi_get_value_string_utf8( - env, parameters[0], eventTypeChars, OHOS::NetManagerStandard::EVENT_ARRAY_LENGTH - 1, &strLen)); - - napi_ref callbackRef = nullptr; - if (parameterCount == PARAMS_COUNT) { - napi_create_reference(env, parameters[1], 1, &callbackRef); - } - napi_value result = nullptr; - uint32_t eventType = GetSocketEventType(eventTypeChars); - struct TcpEventListener listener = {env, eventType, true, callbackRef, objectInfo}; - if (eventType != NONE_EVENT_TYPE) { - napi_delete_reference(env, listener.callbackRef_); - g_tcpEventListenerList.remove_if([objectInfo, eventType](TcpEventListener listener)->bool { - return (listener.tcpSocket_ == objectInfo && listener.eventType_ == eventType); - }); - result = thisVar; - } - - return thisVar; -} - -napi_value TcpRequestConstructor(napi_env env, napi_callback_info info) -{ - std::size_t argc = 1; - napi_value argv[1]; - napi_value thisVar = nullptr; - NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr)); - - auto asyncContext = new TcpBaseContext(); - auto objectInfo = new TCPSocket(*asyncContext); - - if (tcpSocketInstances.size() <= MAX_SOCKET_OBJ_COUNT) { - asyncContext->tcpSocket_ = objectInfo; - tcpSocketInstances[objectInfo] = asyncContext; - } else { - return thisVar; - } - - napi_wrap(env, - thisVar, - objectInfo, - [](napi_env env, void *data, void *hint) { - TCPSocket *objectInfo = (TCPSocket *)data; - if (objectInfo) { - delete objectInfo; - objectInfo = nullptr; - } - }, - nullptr, - nullptr); - return thisVar; -} - -EXTERN_C_START -/* - * UDP Socket register - */ -napi_value RegisterUdpObjectFunction(napi_env env, napi_value exports) -{ - napi_property_descriptor desc[] = { - DECLARE_NAPI_FUNCTION("bind", UdpBind), - DECLARE_NAPI_FUNCTION("connect", UdpConnect), - DECLARE_NAPI_FUNCTION("send", UdpSend), - DECLARE_NAPI_FUNCTION("close", UdpClose), - DECLARE_NAPI_FUNCTION("getState", UdpGetState), - DECLARE_NAPI_FUNCTION("setExtraOptions", UdpSetExtraOptions), - DECLARE_NAPI_FUNCTION("on", UdpOn), - DECLARE_NAPI_FUNCTION("off", UdpOff), - }; - - NAPI_CALL(env, - napi_define_class(env, - "UDPSocket", - NAPI_AUTO_LENGTH, - UdpRequestConstructor, - nullptr, - sizeof(desc) / sizeof(desc[0]), - desc, - &g_UdpSocketConstructorJS)); - return exports; -} - -napi_value CreateUdpObjectFunction(napi_env env, napi_value exports) -{ - napi_property_descriptor desc[] = { - DECLARE_NAPI_FUNCTION("constructUDPSocketInstance", CreateUDPSocket), - }; - - NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc)); - - return exports; -} - -/* - * TCP Socket register - */ -napi_value RegisterTcpObjectFunction(napi_env env, napi_value exports) -{ - napi_property_descriptor desc[] = { - DECLARE_NAPI_FUNCTION("bind", TcpBind), - DECLARE_NAPI_FUNCTION("connect", TcpConnect), - DECLARE_NAPI_FUNCTION("send", TcpSend), - DECLARE_NAPI_FUNCTION("close", TcpClose), - DECLARE_NAPI_FUNCTION("getRemoteAddress", TcpGetRemoteAddress), - DECLARE_NAPI_FUNCTION("getState", TcpGetState), - DECLARE_NAPI_FUNCTION("setExtraOptions", TcpSetExtraOptions), - DECLARE_NAPI_FUNCTION("on", TcpOn), - DECLARE_NAPI_FUNCTION("off", TcpOff), - }; - - NAPI_CALL(env, - napi_define_class(env, - "TCPSocket", - NAPI_AUTO_LENGTH, - TcpRequestConstructor, - nullptr, - sizeof(desc) / sizeof(desc[0]), - desc, - &g_TcpSocketConstructorJS)); - return exports; -} - -napi_value CreateTcpObjectFunction(napi_env env, napi_value exports) -{ - napi_property_descriptor desc[] = { - DECLARE_NAPI_FUNCTION("constructTCPSocketInstance", CreateTCPSocket), - }; - - NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc)); - - return exports; -} -/* - * Module export function - */ -static napi_value Init(napi_env env, napi_value exports) -{ - RegisterUdpObjectFunction(env, exports); - CreateUdpObjectFunction(env, exports); - RegisterTcpObjectFunction(env, exports); - CreateTcpObjectFunction(env, exports); - - return exports; -} - -EXTERN_C_END - -static napi_module g_socketModule = { - .nm_version = 1, - .nm_flags = 0, - .nm_filename = nullptr, - .nm_register_func = Init, - .nm_modname = "net.socket", - .nm_priv = ((void *)0), - .reserved = {(void *)0}, -}; -/* - * Module register function - */ -extern "C" __attribute__((constructor)) void RegisterSocketModule(void) -{ - napi_module_register(&g_socketModule); -} -} // namespace NetManagerStandard -} // namespace OHOS \ No newline at end of file diff --git a/frameworks/js/napi/socket/src/tcp_socket.cpp b/frameworks/js/napi/socket/src/tcp_socket.cpp deleted file mode 100644 index b22bb94ad2b5be7d7bb09371da39ffbf6cfead36..0000000000000000000000000000000000000000 --- a/frameworks/js/napi/socket/src/tcp_socket.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (C) 2021 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 "tcp_socket.h" - -#include "napi_util.h" -#include "netmgr_log_wrapper.h" -#include "node_api_types.h" - -namespace OHOS { -namespace NetManagerStandard { -TCPSocket::TCPSocket(TcpBaseContext remInfo) -{ - this->tcpbaseContext_ = remInfo; -} - -TCPSocket::~TCPSocket() -{ - TcpClose(this->tcpbaseContext_.socketfd_); -} - -void TCPSocket::GetJSParameter(napi_env &env, napi_value *parameters, TcpBaseContext*&asyncContext) -{ - napi_value addressvalue = NapiUtil::GetNamedProperty(env, parameters[0], "address"); - if (addressvalue != nullptr) { - asyncContext->ipAddress = NapiUtil::GetStringFromValue(env, addressvalue); - } - napi_value familyValue = NapiUtil::GetNamedProperty(env, parameters[0], "family"); - if (familyValue != nullptr) { - napi_get_value_int32(env, familyValue, &asyncContext->family); - } - napi_value portValue = NapiUtil::GetNamedProperty(env, parameters[0], "port"); - if (portValue != nullptr) { - napi_get_value_int32(env, portValue, &asyncContext->port); - } - napi_value dataValue = NapiUtil::GetNamedProperty(env, parameters[0], "data"); - if (dataValue != nullptr) { - asyncContext->data = NapiUtil::GetStringFromValue(env, dataValue); - } -} - -void TCPSocket::GetSocketInfo(struct sockaddr_in &addr, TcpBaseContext *&asyncContext) -{ - addr.sin_addr.s_addr = inet_addr(asyncContext->ipAddress.c_str()); - if (asyncContext->family == IPV6) { - addr.sin_family = AF_INET6; - } else { - addr.sin_family = AF_INET; - } - addr.sin_port = htons(asyncContext->port); -} - -int TCPSocket::TcpSocket(int domain, int type, int protocol) -{ - this->tcpbaseContext_.socketfd_ = socket(domain, type, protocol); - return this->tcpbaseContext_.socketfd_; -} - -int TCPSocket::TcpBind(int fd, const struct sockaddr *addr, socklen_t len) -{ - if (fd != this->tcpbaseContext_.socketfd_) { - return -1; - } - return bind(fd, addr, len); -} - -int TCPSocket::TcpConnect(int fd, const struct sockaddr *addr, socklen_t len) -{ - if (fd != this->tcpbaseContext_.socketfd_) { - return -1; - } - return connect(fd, addr, len); -} - -int TCPSocket::TcpSend(int fd, const void *buf, size_t len, int flags) -{ - if (fd != this->tcpbaseContext_.socketfd_) { - return -1; - } - return send(fd, buf, len, flags); -} - -int TCPSocket::TcpClose(int fd) -{ - if (fd != this->tcpbaseContext_.socketfd_) { - return -1; - } - return close(fd); -} - -int TCPSocket::TcpSetSockopt(int fd, int level, int optname, const void *optval, socklen_t optlen) -{ - if (fd != this->tcpbaseContext_.socketfd_) { - return -1; - } - return setsockopt(fd, level, optname, optval, optlen); -} - -void TCPSocket::GetExOpGetJSParameter(napi_env &env, napi_value *parameters, TcpBaseContext*&asyncContext) -{ - bool value = false; - napi_value keepAliveValue = NapiUtil::GetNamedProperty(env, parameters[0], "keepAlive"); - if (keepAliveValue != nullptr) { - napi_get_value_bool(env, keepAliveValue, &value); - } - asyncContext->tcpExtraOptions_.SetKeepAlive(value); - - napi_value OOBInlineValue = NapiUtil::GetNamedProperty(env, parameters[0], "OOBInline"); - if (OOBInlineValue != nullptr) { - napi_get_value_bool(env, OOBInlineValue, &value); - } - asyncContext->tcpExtraOptions_.SetOOBInline(value); - - napi_value TCPNoDelayValue = NapiUtil::GetNamedProperty(env, parameters[0], "TCPNoDelay"); - if (TCPNoDelayValue != nullptr) { - napi_get_value_bool(env, TCPNoDelayValue, &value); - } - asyncContext->tcpExtraOptions_.SetTCPNoDelay(value); - - napi_value socketLingerValue = NapiUtil::GetNamedProperty(env, parameters[0], "socketLinger"); - if (socketLingerValue != nullptr) { - napi_value socktLingerOnValue = NapiUtil::GetNamedProperty(env, socketLingerValue, "on"); - if (socktLingerOnValue != nullptr) { - napi_get_value_bool(env, socktLingerOnValue, &value); - } - asyncContext->tcpExtraOptions_.SetSocketLingerOn(value); - - int32_t intValue = 0; - napi_value socktLingerLingerValue = NapiUtil::GetNamedProperty(env, socketLingerValue, "linger"); - if (socktLingerLingerValue != nullptr) { - napi_get_value_int32(env, socktLingerLingerValue, &intValue); - } - asyncContext->tcpExtraOptions_.SetSocketLingerLinger(value); - } -} -} // namespace NetManagerStandard -} // namespace OHOS \ No newline at end of file diff --git a/frameworks/js/napi/socket/src/udp_socket.cpp b/frameworks/js/napi/socket/src/udp_socket.cpp deleted file mode 100644 index 7a0c79efb485260592bc72623326292d04e75d3b..0000000000000000000000000000000000000000 --- a/frameworks/js/napi/socket/src/udp_socket.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (C) 2021 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 "udp_socket.h" -#include "napi_util.h" -#include "netmgr_log_wrapper.h" -#include "node_api_types.h" - -namespace OHOS { -namespace NetManagerStandard { -UDPSocket::UDPSocket(Baseinfo remInfo) -{ - this->remInfo = remInfo; -} - -UDPSocket::~UDPSocket() -{ - UdpClose(this->remInfo.socketfd); -} - -void UDPSocket::GetJSParameter(napi_env &env, napi_value *parameters, Baseinfo*&asyncContext) -{ - napi_value addressvalue = NapiUtil::GetNamedProperty(env, parameters[0], "address"); - if (addressvalue != nullptr) { - asyncContext->ipAddress = NapiUtil::GetStringFromValue(env, addressvalue); - } - napi_value familyValue = NapiUtil::GetNamedProperty(env, parameters[0], "family"); - if (familyValue != nullptr) { - napi_get_value_int32(env, familyValue, &asyncContext->family); - } - napi_value portValue = NapiUtil::GetNamedProperty(env, parameters[0], "port"); - if (portValue != nullptr) { - napi_get_value_int32(env, portValue, &asyncContext->port); - } - napi_value dataValue = NapiUtil::GetNamedProperty(env, parameters[0], "data"); - if (dataValue != nullptr) { - asyncContext->data = NapiUtil::GetStringFromValue(env, dataValue); - } -} - -void UDPSocket::GetSocketInfo(struct sockaddr_in &addr, Baseinfo *&asyncContext) -{ - addr.sin_addr.s_addr = inet_addr(asyncContext->ipAddress.c_str()); - if (asyncContext->family == IPV6) { - addr.sin_family = AF_INET6; - } else { - addr.sin_family = AF_INET; - } - addr.sin_port = htons(asyncContext->port); -} - -int UDPSocket::UdpSocket(int domain, int type, int protocol) -{ - this->remInfo.socketfd = socket(domain, type, protocol); - return this->remInfo.socketfd; -} - -int UDPSocket::UdpBind(int fd, const struct sockaddr *addr, socklen_t len) -{ - if (fd != this->remInfo.socketfd) { - return -1; - } - return bind(fd, addr, len); -} - -int UDPSocket::UdpConnect(int fd, const struct sockaddr *addr, socklen_t len) -{ - if (fd != this->remInfo.socketfd) { - return -1; - } - return connect(fd, addr, len); -} - -int UDPSocket::UdpSend(int fd, const void *buf, size_t len, int flags) -{ - if (fd != this->remInfo.socketfd) { - return -1; - } - return send(fd, buf, len, flags); -} - -int UDPSocket::UdpClose(int fd) -{ - if (fd != this->remInfo.socketfd) { - return -1; - } - return close(fd); -} -} // namespace NetManagerStandard -} // namespace OHOS \ No newline at end of file diff --git a/frameworks/js/napi/socket/task_queue/include/task_queue.h b/frameworks/js/napi/socket/task_queue/include/task_queue.h new file mode 100644 index 0000000000000000000000000000000000000000..7ab8770e2722963bbc08355016a241db7ea5eef6 --- /dev/null +++ b/frameworks/js/napi/socket/task_queue/include/task_queue.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2022 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_TASK_QUEUE_H +#define COMMUNICATIONNETSTACK_TASK_QUEUE_H + +#include "netstack_base_context.h" + +namespace OHOS::NetStack::Task { + +enum class TaskPriority { + CLOSE, + SEND, + CONNECT, + BIND, + SET_OPTIONS, +}; + +void Executor(napi_env env, void *data); + +void Callback(napi_env env, napi_status status, void *data); + +void PushTask(TaskPriority priority, AsyncWorkExecutor executor, AsyncWorkCallback callback, void *data); + +} // namespace OHOS::NetStack::Task + +#endif /* COMMUNICATIONNETSTACK_TASK_QUEUE_H */ diff --git a/frameworks/js/napi/socket/task_queue/src/task_queue.cpp b/frameworks/js/napi/socket/task_queue/src/task_queue.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ee1612d67854d1060d257ae7624751daa5f66de0 --- /dev/null +++ b/frameworks/js/napi/socket/task_queue/src/task_queue.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2022 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 "task_queue.h" +#include "netstack_log.h" +#include +#include +#include + +namespace OHOS::NetStack::Task { + +class Task { +public: + Task() = delete; + + Task(TaskPriority priority, AsyncWorkExecutor exec, AsyncWorkCallback call, void *d) + : executor(exec), callback(call), data(d), priority_(priority) + { + } + + ~Task() = default; + + bool operator<(const Task &e) const + { + return priority_ < e.priority_; + } + + AsyncWorkExecutor executor; + AsyncWorkCallback callback; + void *data; + +private: + TaskPriority priority_; +}; + +std::priority_queue g_taskExecutorQueue; /* NOLINT */ + +std::priority_queue g_taskCallbackQueue; /* NOLINT */ + +std::mutex g_mutex; + +void Executor(napi_env env, void *data) +{ + std::lock_guard lock(g_mutex); + + if (g_taskExecutorQueue.empty()) { + NETSTACK_LOGI("queue is empty"); + return; + } + + auto context = static_cast(data); + context->SetExecOK(true); + + Task task = g_taskExecutorQueue.top(); + g_taskExecutorQueue.pop(); + task.executor(env, task.data); + g_taskCallbackQueue.push(task); +} + +void Callback(napi_env env, napi_status status, void *data) +{ + std::lock_guard lock(g_mutex); + + (void)status; + + auto deleter = [](BaseContext *context) { delete context; }; + std::unique_ptr context(static_cast(data), deleter); + + if (!context->IsExecOK()) { + NETSTACK_LOGI("new async work again to read the task queue"); + auto again = new BaseContext(env, nullptr); + again->CreateAsyncWork(context->GetAsyncWorkName(), Executor, Callback); + } + + if (g_taskCallbackQueue.empty()) { + return; + } + + Task task = g_taskCallbackQueue.top(); + g_taskCallbackQueue.pop(); + task.callback(env, napi_ok, task.data); +} + +void PushTask(TaskPriority priority, AsyncWorkExecutor executor, AsyncWorkCallback callback, void *data) +{ + std::lock_guard lock(g_mutex); + + g_taskExecutorQueue.push(Task(priority, executor, callback, data)); +} + +} // namespace OHOS::NetStack::Task diff --git a/frameworks/js/napi/websocket/include/websocket_napi.h b/frameworks/js/napi/websocket/include/websocket_napi.h index dc70feb7ebec0fae16f9e2938b2fccd35c0e5543..a2ddffdd7b30d5829606e08a1ecfb2629e8173fc 100644 --- a/frameworks/js/napi/websocket/include/websocket_napi.h +++ b/frameworks/js/napi/websocket/include/websocket_napi.h @@ -20,7 +20,7 @@ #include "napi/native_node_api.h" namespace OHOS { -namespace NetManagerStandard { -} // namespace NetManagerStandard +namespace NetStack { +} // namespace NetStack } // namespace OHOS #endif // WEBSOCKET_NAPI_H \ No newline at end of file diff --git a/frameworks/js/napi/websocket/src/websocket_napi.cpp b/frameworks/js/napi/websocket/src/websocket_napi.cpp index 08db278c9e5449b6007032ffeb53b59112a45cb1..b7327a76fc239ef5dfc4ed1cfc7d5c2685116ea6 100644 --- a/frameworks/js/napi/websocket/src/websocket_napi.cpp +++ b/frameworks/js/napi/websocket/src/websocket_napi.cpp @@ -14,9 +14,9 @@ */ #include "websocket_napi.h" -#include "netmgr_log_wrapper.h" +#include "netstack_log.h" namespace OHOS { -namespace NetManagerStandard { -} // namespace NetManagerStandard +namespace NetStack { +} // namespace NetStack } // namespace OHOS diff --git a/test/napi/common/test_common.h b/test/napi/common/test_common.h new file mode 100644 index 0000000000000000000000000000000000000000..e78a17f9ccfc6438d7a76165881e65cc31a80d0e --- /dev/null +++ b/test/napi/common/test_common.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2021-2022 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_TEST_COMMON_H +#define COMMUNICATIONNETSTACK_TEST_COMMON_H + +#include "native_engine/native_engine.h" +#include "native_value/quickjs_native_value.h" +#include "netstack_log.h" +#include "netstack_napi_utils.h" +#include "quickjs_native_engine.h" +#include "gtest/gtest.h" +#include + +static uint32_t g_testNum = 0; + +static uint32_t testNumber = 1; + +#define ASSERT_CHECK_CALL(call) \ + do { \ + ASSERT_EQ(call, napi_ok); \ + } while (0) + +#define ASSERT_CHECK_VALUE_TYPE(env, value, type) \ + do { \ + napi_valuetype valueType = napi_undefined; \ + ASSERT_TRUE((value) != nullptr); \ + ASSERT_CHECK_CALL(napi_typeof(env, value, &valueType)); \ + ASSERT_EQ(valueType, type); \ + } while (0) + +#define ASSERT_VALUE_IS_PROMISE(env, value) \ + do { \ + bool ret = false; \ + napi_is_promise(env, value, &ret); \ + ASSERT_TRUE(ret); \ + } while (0) + +class NativeEngineTest : public testing::Test { +public: + NativeEngineTest(); + ~NativeEngineTest() override; + void SetUp() override {} + void TearDown() override {} + +protected: + NativeEngine *engine_; +}; + +static NativeEngine *g_nativeEngine = nullptr; + +NativeEngineTest::NativeEngineTest() : engine_(g_nativeEngine) {} + +NativeEngineTest::~NativeEngineTest() = default; + +#endif /* COMMUNICATIONNETSTACK_TEST_COMMON_H */ diff --git a/test/napi/http/CMakeLists.txt b/test/napi/http/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..ba0821ef0856dc2977da5705973b57da235cb896 --- /dev/null +++ b/test/napi/http/CMakeLists.txt @@ -0,0 +1,60 @@ +# Copyright (C) 2021-2022 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_directories(../../../frameworks/js/napi/http/http_module/include) +include_directories(../../../frameworks/js/napi/http/async_work/include) +include_directories(../../../frameworks/js/napi/http/http_exec/include) +include_directories(../../../frameworks/js/napi/http/constant/include) +include_directories(../../../frameworks/js/napi/http/async_context/include) +include_directories(../../../frameworks/js/napi/http/options/include) + +include_directories(../../../../../../third_party/curl/include) + +link_directories(../../../../../../third_party/curl/cmake-build-debug/lib) + +add_executable( + test_napi_http_exec + test_napi_exec.cpp + ../log/test_hilog.cpp + + ../../../frameworks/js/napi/http/http_module/src/http_module.cpp + ../../../frameworks/js/napi/http/constant/src/constant.cpp + ../../../frameworks/js/napi/http/async_context/src/request_context.cpp + ../../../frameworks/js/napi/http/async_work/src/http_async_work.cpp + ../../../frameworks/js/napi/http/options/src/http_response.cpp + ../../../frameworks/js/napi/http/options/src/http_request_options.cpp + ../../../frameworks/js/napi/http/http_exec/src/http_exec.cpp +) + +target_link_libraries(test_napi_http_exec curl-d) +target_link_libraries(test_napi_http_exec ace_napi_quickjs) +target_link_libraries(test_napi_http_exec quickjs) +target_link_libraries(test_napi_http_exec uv) +target_link_libraries(test_napi_http_exec securec) +target_link_libraries(test_napi_http_exec gtestd) +target_link_libraries(test_napi_http_exec gmockd) +target_link_libraries(test_napi_http_exec gtest_maind) +target_link_libraries(test_napi_http_exec gmock_maind) +target_link_libraries(test_napi_http_exec pthread) +target_link_libraries(test_napi_http_exec dl) +target_link_libraries(test_napi_http_exec nghttp2) +target_link_libraries(test_napi_http_exec netstack_utils) + +add_compile_definitions(NO_SSL_CERTIFICATION=0) +add_compile_definitions(HTTP_CURL_PRINT_VERBOSE=0) +add_compile_definitions(NETSTACK_USE_PROXY=0) +add_compile_definitions(NETSTACK_PROXY_URL_PORT="xxxx:xxxx") +add_compile_definitions(NETSTACK_PROXY_TYPE=CURLPROXY_HTTP) +add_compile_definitions(NETSTACK_PROXY_PASS="xxxx:xxxx") +add_compile_definitions(SERVER_IP="x.x.x.x") +set(CMAKE_CXX_FLAGS -g) diff --git a/test/napi/http/test_napi_exec.cpp b/test/napi/http/test_napi_exec.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c8b5bd1ec16712dbf0b22c5404879a0002cc1a79 --- /dev/null +++ b/test/napi/http/test_napi_exec.cpp @@ -0,0 +1,649 @@ +/* + * Copyright (C) 2021-2022 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 "test_common.h" + +#include "constant.h" +#include "http_module.h" +#include "securec.h" + +#define COMMON_DECLARE1 \ + auto env = (napi_env)engine_; \ + \ + napi_value exports = NapiUtils::CreateObject(env); \ + \ + HttpModuleExports::InitHttpModule(env, exports); \ + napi_value requestMethod = NapiUtils::GetNamedProperty(env, exports, HttpModuleExports::INTERFACE_REQUEST_METHOD); \ + \ + std::string methodGet = NapiUtils::GetStringPropertyUtf8(env, requestMethod, HttpConstant::HTTP_METHOD_GET); \ + ASSERT_EQ(methodGet, HttpConstant::HTTP_METHOD_GET); + +#define COMMON_DECLARE2 \ + napi_value responseCode = NapiUtils::GetNamedProperty(env, exports, HttpModuleExports::INTERFACE_RESPONSE_CODE); \ + uint32_t codeOK = NapiUtils::GetUint32Property(env, responseCode, "OK"); \ + ASSERT_EQ(codeOK, (uint32_t)HttpModuleExports::ResponseCode::OK); \ + \ + napi_value createHttpFunc = NapiUtils::GetNamedProperty(env, exports, HttpModuleExports::FUNCTION_CREATE_HTTP); \ + ASSERT_CHECK_VALUE_TYPE(env, createHttpFunc, napi_function); + +#define COMMON_DECLARE3 \ + napi_value httpRequestValue = NapiUtils::CallFunction(env, exports, createHttpFunc, 0, nullptr); \ + ASSERT_CHECK_VALUE_TYPE(env, httpRequestValue, napi_object); \ + \ + napi_value requestFunc = \ + NapiUtils::GetNamedProperty(env, httpRequestValue, HttpModuleExports::HttpRequest::FUNCTION_REQUEST); \ + ASSERT_CHECK_VALUE_TYPE(env, requestFunc, napi_function); + +#define ON_HEADER_RECEIVE "headerReceive" + +#define DEFINE_TEST_BEGIN(name, ASSERT_CODE_OK) \ + [[maybe_unused]] HWTEST_F(NativeEngineTest, /* NOLINT */ \ + name, testing::ext::TestSize.Level0) \ + { \ + COMMON_DECLARE1 \ + COMMON_DECLARE2 \ + COMMON_DECLARE3 \ + auto callbackOneParam = NapiUtils::CreateFunction(env, #name "CallbackOneParam", \ + MAKE_CALLBACK_ONE_PARAM(#name, ASSERT_CODE_OK), nullptr); \ + auto callbackTwoParam = NapiUtils::CreateFunction(env, #name "CallbackTwoParam", \ + MAKE_CALLBACK_TWO_PARAM(#name, ASSERT_CODE_OK), nullptr); + +#define DEFINE_TEST_END } + +#define MAKE_CALLBACK_ONE_PARAM(FUNC_NAME, ASSERT_CODE_OK) \ + [](napi_env env, napi_callback_info info) -> napi_value { \ + NETSTACK_LOGI("%s", FUNC_NAME); \ + \ + napi_value thisVal = nullptr; \ + size_t paramsCount = 1; \ + napi_value params[1] = {nullptr}; \ + NAPI_CALL(env, napi_get_cb_info(env, info, ¶msCount, params, &thisVal, nullptr)); \ + \ + if (NapiUtils::GetValueType(env, params[0]) != napi_undefined) { \ + if (NapiUtils::HasNamedProperty(env, params[0], HttpConstant::RESPONSE_KEY_RESPONSE_CODE)) { \ + uint32_t code = \ + NapiUtils::GetUint32Property(env, params[0], HttpConstant::RESPONSE_KEY_RESPONSE_CODE); \ + \ + assert((code == (uint32_t)HttpModuleExports::ResponseCode::OK) == ASSERT_CODE_OK); \ + } \ + \ + if (NapiUtils::HasNamedProperty(env, params[0], HttpConstant::RESPONSE_KEY_COOKIES)) { \ + std::string cookies = \ + NapiUtils::GetStringPropertyUtf8(env, params[0], HttpConstant::RESPONSE_KEY_COOKIES); \ + \ + NETSTACK_LOGI("cookies:\n%s", cookies.c_str()); \ + } \ + \ + napi_value header; \ + if (NapiUtils::HasNamedProperty(env, params[0], HttpConstant::RESPONSE_KEY_HEADER)) { \ + header = \ + OHOS::NetStack::NapiUtils::GetNamedProperty(env, params[0], HttpConstant::RESPONSE_KEY_HEADER); \ + auto names = OHOS::NetStack::NapiUtils::GetPropertyNames(env, header); \ + std::for_each(names.begin(), names.end(), [env, header](const std::string &name) { \ + auto value = OHOS::NetStack::NapiUtils::GetStringPropertyUtf8(env, header, name); \ + NETSTACK_LOGI("name = %s; value = %s", name.c_str(), value.c_str()); \ + }); \ + } else { \ + NETSTACK_LOGI("##### Once Header Receive"); \ + header = params[0]; \ + auto names = OHOS::NetStack::NapiUtils::GetPropertyNames(env, header); \ + NETSTACK_LOGI("names size = %zu", names.size()); \ + std::for_each(names.begin(), names.end(), [env, header](const std::string &name) { \ + auto value = OHOS::NetStack::NapiUtils::GetStringPropertyUtf8(env, header, name); \ + NETSTACK_LOGI("Once Header name = %s; value = %s", name.c_str(), value.c_str()); \ + }); \ + } \ + \ + if (NapiUtils::HasNamedProperty(env, params[0], HttpConstant::RESPONSE_KEY_RESULT)) { \ + napi_value result = NapiUtils::GetNamedProperty(env, params[0], HttpConstant::RESPONSE_KEY_RESULT); \ + \ + if (NapiUtils::GetValueType(env, result) == napi_string) { \ + std::string data = OHOS::NetStack::NapiUtils::GetStringFromValueUtf8(env, result); \ + NETSTACK_LOGI("data:\n%s", data.c_str()); \ + } else if (NapiUtils::ValueIsArrayBuffer(env, result)) { \ + size_t length = 0; \ + void *data = NapiUtils::GetInfoFromArrayBufferValue(env, result, &length); \ + FILE *fp = fopen("mine.png", "wb"); \ + NETSTACK_LOGI("png size is is %zu", length); \ + if (fp != nullptr) { \ + fwrite(data, 1, length, fp); \ + fclose(fp); \ + } \ + } \ + } \ + } \ + \ + NETSTACK_LOGI("\n\n\n"); \ + return NapiUtils::GetUndefined(env); \ + } + +#define MAKE_CALLBACK_TWO_PARAM(FUNC_NAME, ASSERT_CODE_OK) \ + [](napi_env env, napi_callback_info info) -> napi_value { \ + NETSTACK_LOGI("%s", FUNC_NAME); \ + \ + napi_value thisVal = nullptr; \ + size_t paramsCount = 2; \ + napi_value params[2] = {nullptr}; \ + NAPI_CALL(env, napi_get_cb_info(env, info, ¶msCount, params, &thisVal, nullptr)); \ + \ + bool typeRight = ((NapiUtils::GetValueType(env, params[0]) == napi_undefined && \ + NapiUtils::GetValueType(env, params[1]) != napi_undefined) || \ + (NapiUtils::GetValueType(env, params[0]) != napi_undefined && \ + NapiUtils::GetValueType(env, params[1]) == napi_undefined)); \ + assert(typeRight); \ + \ + if (NapiUtils::GetValueType(env, params[1]) != napi_undefined) { \ + if (NapiUtils::HasNamedProperty(env, params[1], HttpConstant::RESPONSE_KEY_RESPONSE_CODE)) { \ + uint32_t code = \ + NapiUtils::GetUint32Property(env, params[1], HttpConstant::RESPONSE_KEY_RESPONSE_CODE); \ + \ + assert((code == (uint32_t)HttpModuleExports::ResponseCode::OK) == ASSERT_CODE_OK); \ + } \ + \ + if (NapiUtils::HasNamedProperty(env, params[1], HttpConstant::RESPONSE_KEY_COOKIES)) { \ + std::string cookies = \ + NapiUtils::GetStringPropertyUtf8(env, params[1], HttpConstant::RESPONSE_KEY_COOKIES); \ + \ + NETSTACK_LOGI("cookies:\n%s", cookies.c_str()); \ + } \ + \ + napi_value header; \ + if (NapiUtils::HasNamedProperty(env, params[1], HttpConstant::RESPONSE_KEY_HEADER)) { \ + header = \ + OHOS::NetStack::NapiUtils::GetNamedProperty(env, params[1], HttpConstant::RESPONSE_KEY_HEADER); \ + auto names = OHOS::NetStack::NapiUtils::GetPropertyNames(env, header); \ + std::for_each(names.begin(), names.end(), [env, header](const std::string &name) { \ + auto value = OHOS::NetStack::NapiUtils::GetStringPropertyUtf8(env, header, name); \ + NETSTACK_LOGI("name = %s; value = %s", name.c_str(), value.c_str()); \ + }); \ + } else { \ + NETSTACK_LOGI("##### On Header Receive"); \ + header = params[1]; \ + auto names = OHOS::NetStack::NapiUtils::GetPropertyNames(env, header); \ + NETSTACK_LOGI("names size = %zu", names.size()); \ + std::for_each(names.begin(), names.end(), [env, header](const std::string &name) { \ + auto value = OHOS::NetStack::NapiUtils::GetStringPropertyUtf8(env, header, name); \ + NETSTACK_LOGI("Header name = %s; value = %s", name.c_str(), value.c_str()); \ + }); \ + } \ + \ + if (NapiUtils::HasNamedProperty(env, params[1], HttpConstant::RESPONSE_KEY_RESULT)) { \ + napi_value result = NapiUtils::GetNamedProperty(env, params[1], HttpConstant::RESPONSE_KEY_RESULT); \ + \ + if (NapiUtils::GetValueType(env, result) == napi_string) { \ + std::string data = OHOS::NetStack::NapiUtils::GetStringFromValueUtf8(env, result); \ + NETSTACK_LOGI("data:\n%s", data.c_str()); \ + } else if (NapiUtils::ValueIsArrayBuffer(env, result)) { \ + size_t length = 0; \ + void *data = NapiUtils::GetInfoFromArrayBufferValue(env, result, &length); \ + FILE *fp = fopen("mine.png", "wb"); \ + NETSTACK_LOGI("png size is is %zu", length); \ + if (fp != nullptr) { \ + fwrite(data, 1, length, fp); \ + fclose(fp); \ + } \ + } \ + } \ + } else if (NapiUtils::GetValueType(env, params[0]) != napi_undefined) { \ + int32_t code = NapiUtils::GetInt32Property(env, params[0], "code"); \ + NETSTACK_LOGI("error code = %d\n", code); \ + } else { \ + NETSTACK_LOGI("error is undefined"); \ + } \ + \ + NETSTACK_LOGI("\n\n\n"); \ + return NapiUtils::GetUndefined(env); \ + } + +namespace OHOS::NetStack { + +void CallOn(napi_env env, napi_value thisVal, napi_value callback) +{ + napi_value func = NapiUtils::GetNamedProperty(env, thisVal, HttpModuleExports::HttpRequest::FUNCTION_ON); + + napi_value argv[2] = {NapiUtils::CreateStringUtf8(env, ON_HEADER_RECEIVE), callback}; + + NapiUtils::CallFunction(env, thisVal, func, 2, argv); +} + +void CallOnce(napi_env env, napi_value thisVal, napi_value callback) +{ + napi_value func = NapiUtils::GetNamedProperty(env, thisVal, HttpModuleExports::HttpRequest::FUNCTION_ONCE); + + napi_value argv[2] = {NapiUtils::CreateStringUtf8(env, ON_HEADER_RECEIVE), callback}; + + NapiUtils::CallFunction(env, thisVal, func, 2, argv); +} + +void CallOff(napi_env env, napi_value thisVal, napi_value callback) +{ + napi_value func = NapiUtils::GetNamedProperty(env, thisVal, HttpModuleExports::HttpRequest::FUNCTION_OFF); + + napi_value argv[2] = {NapiUtils::CreateStringUtf8(env, ON_HEADER_RECEIVE), callback}; + + NapiUtils::CallFunction(env, thisVal, func, 2, argv); +} + +void CallPromiseThenCatch(napi_env env, napi_value promise, napi_value callback) +{ + bool isPromise = false; + napi_is_promise(env, promise, &isPromise); + if (!isPromise) { + return; + } + + JSValue quickJsPromise = reinterpret_cast(promise)->GetJsValue(); + + JSContext *ctx = ((QuickJSNativeEngine *)g_nativeEngine)->GetContext(); + + JSValue then = JS_GetPropertyStr(ctx, quickJsPromise, "then"); + JSValue callbackValue = reinterpret_cast(callback)->GetJsValue(); + JS_Call(ctx, then, quickJsPromise, 1, &callbackValue); + + JSValue theCatch = JS_GetPropertyStr(ctx, quickJsPromise, "catch"); + JSValue callbackValueCatch = reinterpret_cast(callback)->GetJsValue(); + JS_Call(ctx, theCatch, quickJsPromise, 1, &callbackValueCatch); +} + +DEFINE_TEST_BEGIN(TestHttpModuleMethodGetExtraDataNameValue, true) +{ + napi_value urlValue = NapiUtils::CreateStringUtf8(env, "https://" SERVER_IP); + + napi_value options = NapiUtils::CreateObject(env); + + napi_value header = NapiUtils::CreateObject(env); + NapiUtils::SetStringPropertyUtf8(env, header, "no-use", "no use header"); + NapiUtils::SetStringPropertyUtf8(env, header, "just-test", "just test header"); + + napi_value extraData = NapiUtils::CreateObject(env); + NapiUtils::SetStringPropertyUtf8(env, (napi_value)extraData, "南京", "首府"); + NapiUtils::SetStringPropertyUtf8(env, (napi_value)extraData, "天气", "北京"); + + NapiUtils::SetNamedProperty(env, options, std::string(HttpConstant::PARAM_KEY_HEADER), header); + NapiUtils::SetNamedProperty(env, options, std::string(HttpConstant::PARAM_KEY_EXTRA_DATA), extraData); + + napi_value args[3] = {urlValue, options, callbackTwoParam}; + + napi_value retValue = NapiUtils::CallFunction(env, httpRequestValue, requestFunc, 3, args); + ASSERT_CHECK_VALUE_TYPE(env, retValue, napi_undefined); + + retValue = NapiUtils::CallFunction(env, httpRequestValue, requestFunc, 2, args); + ASSERT_VALUE_IS_PROMISE(env, retValue); + CallPromiseThenCatch(env, retValue, callbackOneParam); +} +DEFINE_TEST_END + +DEFINE_TEST_BEGIN(TestHttpModuleMethodGetExtraDataNameValueUrlHasPara, true) +{ + napi_value urlValue = NapiUtils::CreateStringUtf8(env, "https://" SERVER_IP "?name=Mao"); + + napi_value options = NapiUtils::CreateObject(env); + + napi_value header = NapiUtils::CreateObject(env); + NapiUtils::SetStringPropertyUtf8(env, header, "no-use", "no use header"); + NapiUtils::SetStringPropertyUtf8(env, header, "just-test", "just test header"); + + napi_value extraData = NapiUtils::CreateObject(env); + NapiUtils::SetStringPropertyUtf8(env, (napi_value)extraData, "南京", "首府"); + NapiUtils::SetStringPropertyUtf8(env, (napi_value)extraData, "天气", "北京"); + + NapiUtils::SetNamedProperty(env, options, std::string(HttpConstant::PARAM_KEY_HEADER), header); + NapiUtils::SetNamedProperty(env, options, std::string(HttpConstant::PARAM_KEY_EXTRA_DATA), extraData); + + napi_value args[3] = {urlValue, options, callbackTwoParam}; + + napi_value retValue = NapiUtils::CallFunction(env, httpRequestValue, requestFunc, 3, args); + ASSERT_CHECK_VALUE_TYPE(env, retValue, napi_undefined); + + retValue = NapiUtils::CallFunction(env, httpRequestValue, requestFunc, 2, args); + ASSERT_VALUE_IS_PROMISE(env, retValue); + CallPromiseThenCatch(env, retValue, callbackOneParam); +} +DEFINE_TEST_END + +DEFINE_TEST_BEGIN(TestHttpModuleMethodGetExtraDataNameValueUrlHasParaNoEncode, true) +{ + napi_value urlValue = NapiUtils::CreateStringUtf8(env, "https://" SERVER_IP "?name=Mao"); + + napi_value options = NapiUtils::CreateObject(env); + + napi_value header = NapiUtils::CreateObject(env); + NapiUtils::SetStringPropertyUtf8(env, header, "no-use", "no use header"); + NapiUtils::SetStringPropertyUtf8(env, header, "just-test", "just test header"); + + napi_value extraData = NapiUtils::CreateObject(env); + NapiUtils::SetStringPropertyUtf8(env, (napi_value)extraData, "age", "199"); + NapiUtils::SetStringPropertyUtf8(env, (napi_value)extraData, "country", "China"); + + NapiUtils::SetNamedProperty(env, options, std::string(HttpConstant::PARAM_KEY_HEADER), header); + NapiUtils::SetNamedProperty(env, options, std::string(HttpConstant::PARAM_KEY_EXTRA_DATA), extraData); + + napi_value args[3] = {urlValue, options, callbackTwoParam}; + + napi_value retValue = NapiUtils::CallFunction(env, httpRequestValue, requestFunc, 3, args); + ASSERT_CHECK_VALUE_TYPE(env, retValue, napi_undefined); + + retValue = NapiUtils::CallFunction(env, httpRequestValue, requestFunc, 2, args); + ASSERT_VALUE_IS_PROMISE(env, retValue); + CallPromiseThenCatch(env, retValue, callbackOneParam); +} +DEFINE_TEST_END + +DEFINE_TEST_BEGIN(TestHttpModuleMethodGetExtraDataString, true) +{ + napi_value urlValue = NapiUtils::CreateStringUtf8(env, "https://" SERVER_IP "?name=Mao"); + + napi_value options = NapiUtils::CreateObject(env); + + napi_value header = NapiUtils::CreateObject(env); + NapiUtils::SetStringPropertyUtf8(env, header, "no-use", "no use header"); + NapiUtils::SetStringPropertyUtf8(env, header, "just-test", "just test header"); + + napi_value extraData = NapiUtils::CreateStringUtf8(env, "this-is-my-get-string=mao&this-test=age"); + + NapiUtils::SetNamedProperty(env, options, std::string(HttpConstant::PARAM_KEY_HEADER), header); + NapiUtils::SetNamedProperty(env, options, std::string(HttpConstant::PARAM_KEY_EXTRA_DATA), extraData); + + napi_value args[3] = {urlValue, options, callbackTwoParam}; + + napi_value retValue = NapiUtils::CallFunction(env, httpRequestValue, requestFunc, 3, args); + ASSERT_CHECK_VALUE_TYPE(env, retValue, napi_undefined); + + retValue = NapiUtils::CallFunction(env, httpRequestValue, requestFunc, 2, args); + ASSERT_VALUE_IS_PROMISE(env, retValue); + CallPromiseThenCatch(env, retValue, callbackOneParam); +} +DEFINE_TEST_END + +DEFINE_TEST_BEGIN(TestHttpModuleMethodGetNoExtraData, true) +{ + napi_value urlValue = NapiUtils::CreateStringUtf8(env, "https://" SERVER_IP "?name=Mao"); + + napi_value options = NapiUtils::CreateObject(env); + + napi_value header = NapiUtils::CreateObject(env); + NapiUtils::SetStringPropertyUtf8(env, header, "no-use", "no use header"); + NapiUtils::SetStringPropertyUtf8(env, header, "just-test", "just test header"); + + NapiUtils::SetNamedProperty(env, options, std::string(HttpConstant::PARAM_KEY_HEADER), header); + + napi_value args[3] = {urlValue, options, callbackTwoParam}; + + napi_value retValue = NapiUtils::CallFunction(env, httpRequestValue, requestFunc, 3, args); + ASSERT_CHECK_VALUE_TYPE(env, retValue, napi_undefined); + + retValue = NapiUtils::CallFunction(env, httpRequestValue, requestFunc, 2, args); + ASSERT_VALUE_IS_PROMISE(env, retValue); + CallPromiseThenCatch(env, retValue, callbackOneParam); +} +DEFINE_TEST_END + +DEFINE_TEST_BEGIN(TestHttpModuleMethodGetExtraDataNullString, true) +{ + napi_value urlValue = NapiUtils::CreateStringUtf8(env, "https://" SERVER_IP "?name=Mao"); + + napi_value options = NapiUtils::CreateObject(env); + + napi_value header = NapiUtils::CreateObject(env); + NapiUtils::SetStringPropertyUtf8(env, header, "no-use", "no use header"); + NapiUtils::SetStringPropertyUtf8(env, header, "just-test", "just test header"); + + napi_value extraData = NapiUtils::CreateStringUtf8(env, ""); + + NapiUtils::SetNamedProperty(env, options, std::string(HttpConstant::PARAM_KEY_HEADER), header); + NapiUtils::SetNamedProperty(env, options, std::string(HttpConstant::PARAM_KEY_EXTRA_DATA), extraData); + + napi_value args[3] = {urlValue, options, callbackTwoParam}; + + napi_value retValue = NapiUtils::CallFunction(env, httpRequestValue, requestFunc, 3, args); + ASSERT_CHECK_VALUE_TYPE(env, retValue, napi_undefined); + + retValue = NapiUtils::CallFunction(env, httpRequestValue, requestFunc, 2, args); + ASSERT_VALUE_IS_PROMISE(env, retValue); + CallPromiseThenCatch(env, retValue, callbackOneParam); +} +DEFINE_TEST_END + +DEFINE_TEST_BEGIN(TestHttpModuleMethodAndHeaderByDefaultHasPara, true) +{ + napi_value urlValue = NapiUtils::CreateStringUtf8(env, "https://" SERVER_IP "?name=Mao"); + + napi_value options = NapiUtils::CreateObject(env); + + napi_value extraData = NapiUtils::CreateObject(env); + NapiUtils::SetStringPropertyUtf8(env, (napi_value)extraData, "age", "199"); + NapiUtils::SetStringPropertyUtf8(env, (napi_value)extraData, "country", "China"); + + NapiUtils::SetNamedProperty(env, options, std::string(HttpConstant::PARAM_KEY_EXTRA_DATA), extraData); + + napi_value args[3] = {urlValue, options, callbackTwoParam}; + + napi_value retValue = NapiUtils::CallFunction(env, httpRequestValue, requestFunc, 3, args); + ASSERT_CHECK_VALUE_TYPE(env, retValue, napi_undefined); + + retValue = NapiUtils::CallFunction(env, httpRequestValue, requestFunc, 2, args); + ASSERT_VALUE_IS_PROMISE(env, retValue); + CallPromiseThenCatch(env, retValue, callbackOneParam); +} +DEFINE_TEST_END + +DEFINE_TEST_BEGIN(TestHttpModuleMethodAndHeaderByDefault, true) +{ + napi_value urlValue = NapiUtils::CreateStringUtf8(env, "https://" SERVER_IP "?name=Mao"); + + napi_value args[2] = {urlValue, callbackTwoParam}; + + napi_value retValue = NapiUtils::CallFunction(env, httpRequestValue, requestFunc, 2, args); + ASSERT_CHECK_VALUE_TYPE(env, retValue, napi_undefined); + + retValue = NapiUtils::CallFunction(env, httpRequestValue, requestFunc, 1, args); + ASSERT_VALUE_IS_PROMISE(env, retValue); + CallPromiseThenCatch(env, retValue, callbackOneParam); +} +DEFINE_TEST_END + +DEFINE_TEST_BEGIN(TestHttpModuleMethodPostExtraDataString, true) +{ + napi_value urlValue = NapiUtils::CreateStringUtf8(env, "https://" SERVER_IP "?name=Mao"); + + napi_value options = NapiUtils::CreateObject(env); + + napi_value header = NapiUtils::CreateObject(env); + NapiUtils::SetStringPropertyUtf8(env, header, "no-use", "no use header"); + NapiUtils::SetStringPropertyUtf8(env, header, "just-test", "just test header"); + + napi_value extraData = NapiUtils::CreateStringUtf8(env, "Linux Http Test String"); + + NapiUtils::SetNamedProperty(env, options, std::string(HttpConstant::PARAM_KEY_HEADER), header); + NapiUtils::SetNamedProperty(env, options, std::string(HttpConstant::PARAM_KEY_EXTRA_DATA), extraData); + NapiUtils::SetStringPropertyUtf8(env, options, std::string(HttpConstant::PARAM_KEY_METHOD), + std::string(HttpConstant::HTTP_METHOD_POST)); + + napi_value args[3] = {urlValue, options, callbackTwoParam}; + + napi_value retValue = NapiUtils::CallFunction(env, httpRequestValue, requestFunc, 3, args); + ASSERT_CHECK_VALUE_TYPE(env, retValue, napi_undefined); + + retValue = NapiUtils::CallFunction(env, httpRequestValue, requestFunc, 2, args); + ASSERT_VALUE_IS_PROMISE(env, retValue); + CallPromiseThenCatch(env, retValue, callbackOneParam); +} +DEFINE_TEST_END + +DEFINE_TEST_BEGIN(TestHttpModuleMethodAndHeaderFail, true) +{ + napi_value urlValue = NapiUtils::CreateStringUtf8(env, "https://" SERVER_IP + ":7878" + "?name=Mao"); + + napi_value args[2] = {urlValue, callbackTwoParam}; + + napi_value retValue = NapiUtils::CallFunction(env, httpRequestValue, requestFunc, 2, args); + ASSERT_CHECK_VALUE_TYPE(env, retValue, napi_undefined); + + retValue = NapiUtils::CallFunction(env, httpRequestValue, requestFunc, 1, args); + ASSERT_VALUE_IS_PROMISE(env, retValue); + CallPromiseThenCatch(env, retValue, callbackOneParam); +} +DEFINE_TEST_END + +DEFINE_TEST_BEGIN(TestHttpModuleMethodPostExtraDataArrayBuffer, true) +{ + napi_value urlValue = NapiUtils::CreateStringUtf8(env, "https://" SERVER_IP "?name=Mao"); + + napi_value options = NapiUtils::CreateObject(env); + + napi_value header = NapiUtils::CreateObject(env); + NapiUtils::SetStringPropertyUtf8(env, header, "no-use", "no use header"); + NapiUtils::SetStringPropertyUtf8(env, header, "just-test", "just test header"); + NapiUtils::SetStringPropertyUtf8(env, header, std::string(HttpConstant::HTTP_CONTENT_TYPE), "mine-png"); + + FILE *fp = fopen("for-post.png", "rb"); + fseek(fp, 0L, SEEK_END); + long size = ftell(fp); + void *buffer = malloc(size); + fseek(fp, 0, SEEK_SET); + size_t readSize = fread((void *)buffer, 1, size, fp); + NETSTACK_LOGI("file size = %ld read size = %zu", size, readSize); + + void *data = nullptr; + napi_value extraData = NapiUtils::CreateArrayBuffer(env, readSize, &data); + memcpy_s(data, readSize, buffer, readSize); + + NapiUtils::SetNamedProperty(env, options, std::string(HttpConstant::PARAM_KEY_HEADER), header); + NapiUtils::SetNamedProperty(env, options, std::string(HttpConstant::PARAM_KEY_EXTRA_DATA), extraData); + NapiUtils::SetStringPropertyUtf8(env, options, std::string(HttpConstant::PARAM_KEY_METHOD), + std::string(HttpConstant::HTTP_METHOD_POST)); + + napi_value args[3] = {urlValue, options, callbackTwoParam}; + + napi_value retValue = NapiUtils::CallFunction(env, httpRequestValue, requestFunc, 3, args); + ASSERT_CHECK_VALUE_TYPE(env, retValue, napi_undefined); + + retValue = NapiUtils::CallFunction(env, httpRequestValue, requestFunc, 2, args); + ASSERT_VALUE_IS_PROMISE(env, retValue); + CallPromiseThenCatch(env, retValue, callbackOneParam); +} +DEFINE_TEST_END + +DEFINE_TEST_BEGIN(TestHttpModuleMethodGetExtraDataNameValueHeaderKeyMultiCase, true) +{ + napi_value urlValue = NapiUtils::CreateStringUtf8(env, "https://" SERVER_IP "?name=Mao"); + + napi_value options = NapiUtils::CreateObject(env); + + napi_value header = NapiUtils::CreateObject(env); + NapiUtils::SetStringPropertyUtf8(env, header, "no-use", "no use header"); + NapiUtils::SetStringPropertyUtf8(env, header, "NO-USE", "Thanks"); + NapiUtils::SetStringPropertyUtf8(env, header, "just-test", "just test header"); + + NapiUtils::SetNamedProperty(env, options, std::string(HttpConstant::PARAM_KEY_HEADER), header); + + napi_value args[3] = {urlValue, options, callbackTwoParam}; + + napi_value retValue = NapiUtils::CallFunction(env, httpRequestValue, requestFunc, 3, args); + ASSERT_CHECK_VALUE_TYPE(env, retValue, napi_undefined); + + retValue = NapiUtils::CallFunction(env, httpRequestValue, requestFunc, 2, args); + ASSERT_VALUE_IS_PROMISE(env, retValue); + CallPromiseThenCatch(env, retValue, callbackOneParam); +} +DEFINE_TEST_END + +DEFINE_TEST_BEGIN(TestHttpModuleMethodGetOnHeaderReceiveOnce, true) +{ + napi_value urlValue = NapiUtils::CreateStringUtf8(env, "https://" SERVER_IP "?name=Mao"); + + napi_value args[2] = {urlValue, callbackTwoParam}; + + CallOnce(env, httpRequestValue, callbackOneParam); + + napi_value retValue = NapiUtils::CallFunction(env, httpRequestValue, requestFunc, 2, args); + ASSERT_CHECK_VALUE_TYPE(env, retValue, napi_undefined); + + retValue = NapiUtils::CallFunction(env, httpRequestValue, requestFunc, 1, args); + ASSERT_VALUE_IS_PROMISE(env, retValue); + CallPromiseThenCatch(env, retValue, callbackOneParam); +} +DEFINE_TEST_END + +DEFINE_TEST_BEGIN(TestHttpModuleMethodGetOnHeaderReceiveOnOn, true) +{ + napi_value urlValue = NapiUtils::CreateStringUtf8(env, "https://" SERVER_IP "?name=Mao"); + + napi_value args[2] = {urlValue, callbackTwoParam}; + + CallOn(env, httpRequestValue, callbackTwoParam); + + napi_value retValue = NapiUtils::CallFunction(env, httpRequestValue, requestFunc, 2, args); + ASSERT_CHECK_VALUE_TYPE(env, retValue, napi_undefined); + + retValue = NapiUtils::CallFunction(env, httpRequestValue, requestFunc, 1, args); + ASSERT_VALUE_IS_PROMISE(env, retValue); + CallPromiseThenCatch(env, retValue, callbackOneParam); +} +DEFINE_TEST_END + +DEFINE_TEST_BEGIN(TestHttpModuleMethodGetOnHeaderReceiveOff, true) +{ + napi_value urlValue = NapiUtils::CreateStringUtf8(env, "https://" SERVER_IP "?name=Mao"); + + napi_value args[2] = {urlValue, callbackTwoParam}; + + CallOn(env, httpRequestValue, callbackTwoParam); + CallOff(env, httpRequestValue, callbackTwoParam); + + napi_value retValue = NapiUtils::CallFunction(env, httpRequestValue, requestFunc, 2, args); + ASSERT_CHECK_VALUE_TYPE(env, retValue, napi_undefined); + + retValue = NapiUtils::CallFunction(env, httpRequestValue, requestFunc, 1, args); + ASSERT_VALUE_IS_PROMISE(env, retValue); + CallPromiseThenCatch(env, retValue, callbackOneParam); +} +DEFINE_TEST_END + +} // namespace OHOS::NetStack + +int main(int argc, char **argv) +{ + testing::GTEST_FLAG(output) = "xml:./"; + testing::InitGoogleTest(&argc, argv); + + JSRuntime *rt = JS_NewRuntime(); + + if (rt == nullptr) { + return 0; + } + + JSContext *ctx = JS_NewContext(rt); + if (ctx == nullptr) { + return 0; + } + + js_std_add_helpers(ctx, 0, nullptr); + + g_nativeEngine = new QuickJSNativeEngine(rt, ctx, nullptr); // default instance id 0 + + int ret = RUN_ALL_TESTS(); + (void)ret; + + g_nativeEngine->Loop(LOOP_DEFAULT); + /* NETSTACK_LOGI("test all number %u", g_testNum); + for (int i = 0; i < g_testNum; ++i) { + g_nativeEngine->Loop(LOOP_ONCE); + } */ + + return 0; +} \ No newline at end of file diff --git a/test/napi/log/test_hilog.cpp b/test/napi/log/test_hilog.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f1d6bad1072ebb819aba94a3b1ae305e9b740ee8 --- /dev/null +++ b/test/napi/log/test_hilog.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2021-2022 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 "hilog/log.h" +#include "netstack_log.h" + +#include + +namespace OHOS::HiviewDFX { + +constexpr uint32_t MAX_BUFFER_SIZE = 4096; + +static void StripFormatString(const std::string &prefix, std::string &str) +{ + for (auto pos = str.find(prefix, 0); pos != std::string::npos; pos = str.find(prefix, pos)) { + str.erase(pos, prefix.size()); + } +} + +#define PRINT_LOG(LEVEL) \ + do { \ + std::string newFmt(fmt); \ + StripFormatString("{public}", newFmt); \ + StripFormatString("{private}", newFmt); \ + \ + va_list args; \ + va_start(args, fmt); \ + \ + char buf[MAX_BUFFER_SIZE] = {"\0"}; \ + int ret = vsnprintf(buf, sizeof(buf) - 1, newFmt.c_str(), args); \ + if (ret < 0) { \ + return -1; \ + } \ + va_end(args); \ + \ + printf("%s %s\r\n", #LEVEL, buf); \ + fflush(stdout); \ + } while (0) + +int HiLog::Debug(const HiLogLabel &label, const char *fmt, ...) +{ + if (label.domain != NETSTACK_LOG_DOMAIN) { + return 0; + } + PRINT_LOG(Debug); + return 0; +} +int HiLog::Info(const HiLogLabel &label, const char *fmt, ...) +{ + if (label.domain != NETSTACK_LOG_DOMAIN) { + return 0; + } + PRINT_LOG(Info); + return 0; +} +int HiLog::Warn(const HiLogLabel &label, const char *fmt, ...) +{ + if (label.domain != NETSTACK_LOG_DOMAIN) { + return 0; + } + PRINT_LOG(Warn); + return 0; +} +int HiLog::Error(const HiLogLabel &label, const char *fmt, ...) +{ + if (label.domain != NETSTACK_LOG_DOMAIN) { + return 0; + } + PRINT_LOG(Error); + return 0; +} +int HiLog::Fatal(const HiLogLabel &label, const char *fmt, ...) +{ + if (label.domain != NETSTACK_LOG_DOMAIN) { + return 0; + } + PRINT_LOG(Fatal); + return 0; +} + +} // namespace OHOS::HiviewDFX \ No newline at end of file diff --git a/test/napi/socket/CMakeLists.txt b/test/napi/socket/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..edfb1c4ee3fd527b13798e57cdcb05eaee5d3bbb --- /dev/null +++ b/test/napi/socket/CMakeLists.txt @@ -0,0 +1,66 @@ +# Copyright (C) 2021-2022 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_directories(../../../frameworks/js/napi/socket/socket_module/include) +include_directories(../../../frameworks/js/napi/socket/options/include) +include_directories(../../../frameworks/js/napi/socket/async_context/include) +include_directories(../../../frameworks/js/napi/socket/constant/include) +include_directories(../../../frameworks/js/napi/socket/async_work/include) +include_directories(../../../frameworks/js/napi/socket/socket_exec/include) +include_directories(../../../frameworks/js/napi/socket/task_queue/include) + +add_executable( + test_napi_socket_exec + test_napi_exec.cpp + ../log/test_hilog.cpp + + ../../../frameworks/js/napi/socket/socket_module/src/socket_module.cpp + ../../../frameworks/js/napi/socket/options/src/net_address.cpp + ../../../frameworks/js/napi/socket/options/src/extra_options_base.cpp + ../../../frameworks/js/napi/socket/options/src/udp_extra_options.cpp + ../../../frameworks/js/napi/socket/options/src/udp_send_options.cpp + ../../../frameworks/js/napi/socket/options/src/socket_state_base.cpp + ../../../frameworks/js/napi/socket/options/src/socket_remote_info.cpp + ../../../frameworks/js/napi/socket/options/src/tcp_connect_options.cpp + ../../../frameworks/js/napi/socket/options/src/tcp_send_options.cpp + ../../../frameworks/js/napi/socket/options/src/tcp_extra_options.cpp + ../../../frameworks/js/napi/socket/async_context/src/bind_context.cpp + ../../../frameworks/js/napi/socket/async_context/src/common_context.cpp + ../../../frameworks/js/napi/socket/async_context/src/connect_context.cpp + ../../../frameworks/js/napi/socket/async_context/src/udp_send_context.cpp + ../../../frameworks/js/napi/socket/async_context/src/tcp_send_context.cpp + ../../../frameworks/js/napi/socket/async_context/src/tcp_extra_context.cpp + ../../../frameworks/js/napi/socket/async_context/src/udp_extra_context.cpp + ../../../frameworks/js/napi/socket/async_work/src/socket_async_work.cpp + ../../../frameworks/js/napi/socket/socket_exec/src/socket_exec.cpp + ../../../frameworks/js/napi/socket/task_queue/src/task_queue.cpp +) + +target_link_libraries(test_napi_socket_exec ace_napi_quickjs) +target_link_libraries(test_napi_socket_exec quickjs) +target_link_libraries(test_napi_socket_exec uv) +target_link_libraries(test_napi_socket_exec securec) +target_link_libraries(test_napi_socket_exec gtestd) +target_link_libraries(test_napi_socket_exec gmockd) +target_link_libraries(test_napi_socket_exec gtest_maind) +target_link_libraries(test_napi_socket_exec gmock_maind) +target_link_libraries(test_napi_socket_exec pthread) +target_link_libraries(test_napi_socket_exec dl) +target_link_libraries(test_napi_socket_exec netstack_utils) + +add_compile_definitions(LOCAL_IPV4_IP="x.x.x.x") +add_compile_definitions(REMOTE_IPV4_IP="x.x.x.x") +add_compile_definitions(LOCAL_IPV6_IP="::1") +add_compile_definitions(REMOTE_IPV6_IP="::1") + +set(CMAKE_CXX_FLAGS -g) diff --git a/test/napi/socket/test_napi_exec.cpp b/test/napi/socket/test_napi_exec.cpp new file mode 100644 index 0000000000000000000000000000000000000000..13fdc7804ded356ea427f02288cbbc08b2ae68bf --- /dev/null +++ b/test/napi/socket/test_napi_exec.cpp @@ -0,0 +1,346 @@ +/* + * Copyright (C) 2021-2022 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 "test_common.h" + +#include "context_key.h" +#include "event_list.h" +#include "net_address.h" +#include "securec.h" +#include "socket_module.h" + +#define TCP_COMMON_DEFINES \ + auto env = (napi_env)engine_; \ + \ + napi_value exports = NapiUtils::CreateObject(env); \ + \ + SocketModuleExports::InitSocketModule(env, exports); \ + \ + napi_value newTcp = \ + NapiUtils::GetNamedProperty(env, exports, SocketModuleExports::FUNCTION_CONSTRUCTOR_TCP_SOCKET_INSTANCE); \ + ASSERT_CHECK_VALUE_TYPE(env, newTcp, napi_function); \ + \ + napi_value tcpThis = NapiUtils::CallFunction(env, exports, newTcp, 0, nullptr); \ + ASSERT_CHECK_VALUE_TYPE(env, tcpThis, napi_object); \ + \ + napi_value tcpBind = NapiUtils::GetNamedProperty(env, tcpThis, SocketModuleExports::TCPSocket::FUNCTION_BIND); \ + ASSERT_CHECK_VALUE_TYPE(env, tcpBind, napi_function); \ + \ + napi_value tcpConnect = \ + NapiUtils::GetNamedProperty(env, tcpThis, SocketModuleExports::TCPSocket::FUNCTION_CONNECT); \ + ASSERT_CHECK_VALUE_TYPE(env, tcpConnect, napi_function); \ + \ + napi_value tcpSend = NapiUtils::GetNamedProperty(env, tcpThis, SocketModuleExports::TCPSocket::FUNCTION_SEND); \ + ASSERT_CHECK_VALUE_TYPE(env, tcpSend, napi_function); \ + \ + napi_value tcpClose = NapiUtils::GetNamedProperty(env, tcpThis, SocketModuleExports::TCPSocket::FUNCTION_CLOSE); \ + ASSERT_CHECK_VALUE_TYPE(env, tcpClose, napi_function); \ + \ + napi_value tcpGetRemoteAddress = \ + NapiUtils::GetNamedProperty(env, tcpThis, SocketModuleExports::TCPSocket::FUNCTION_GET_REMOTE_ADDRESS); \ + ASSERT_CHECK_VALUE_TYPE(env, tcpGetRemoteAddress, napi_function); \ + \ + napi_value tcpGetState = \ + NapiUtils::GetNamedProperty(env, tcpThis, SocketModuleExports::TCPSocket::FUNCTION_GET_STATE); \ + ASSERT_CHECK_VALUE_TYPE(env, tcpGetState, napi_function); \ + \ + napi_value tcpSetExtraOptions = \ + NapiUtils::GetNamedProperty(env, tcpThis, SocketModuleExports::TCPSocket::FUNCTION_SET_EXTRA_OPTIONS); \ + ASSERT_CHECK_VALUE_TYPE(env, tcpSetExtraOptions, napi_function); \ + \ + napi_value tcpOn = NapiUtils::GetNamedProperty(env, tcpThis, SocketModuleExports::TCPSocket::FUNCTION_ON); \ + ASSERT_CHECK_VALUE_TYPE(env, tcpOn, napi_function); \ + \ + napi_value tcpOff = NapiUtils::GetNamedProperty(env, tcpThis, SocketModuleExports::TCPSocket::FUNCTION_OFF); \ + ASSERT_CHECK_VALUE_TYPE(env, tcpOff, napi_function); + +#define UDP_COMMON_DEFINES \ + auto env = (napi_env)engine_; \ + \ + napi_value exports = NapiUtils::CreateObject(env); \ + \ + SocketModuleExports::InitSocketModule(env, exports); \ + \ + napi_value newUdp = \ + NapiUtils::GetNamedProperty(env, exports, SocketModuleExports::FUNCTION_CONSTRUCTOR_UDP_SOCKET_INSTANCE); \ + ASSERT_CHECK_VALUE_TYPE(env, newUdp, napi_function); \ + \ + napi_value udpThis = NapiUtils::CallFunction(env, exports, newUdp, 0, nullptr); \ + ASSERT_CHECK_VALUE_TYPE(env, udpThis, napi_object); \ + \ + napi_value udpBind = NapiUtils::GetNamedProperty(env, udpThis, SocketModuleExports::UDPSocket::FUNCTION_BIND); \ + ASSERT_CHECK_VALUE_TYPE(env, udpBind, napi_function); \ + \ + napi_value udpSend = NapiUtils::GetNamedProperty(env, udpThis, SocketModuleExports::UDPSocket::FUNCTION_SEND); \ + ASSERT_CHECK_VALUE_TYPE(env, udpSend, napi_function); \ + \ + napi_value udpClose = NapiUtils::GetNamedProperty(env, udpThis, SocketModuleExports::UDPSocket::FUNCTION_CLOSE); \ + ASSERT_CHECK_VALUE_TYPE(env, udpClose, napi_function); \ + \ + napi_value udpGetState = \ + NapiUtils::GetNamedProperty(env, udpThis, SocketModuleExports::UDPSocket::FUNCTION_GET_STATE); \ + ASSERT_CHECK_VALUE_TYPE(env, udpGetState, napi_function); \ + \ + napi_value udpSetExtraOptions = \ + NapiUtils::GetNamedProperty(env, udpThis, SocketModuleExports::UDPSocket::FUNCTION_SET_EXTRA_OPTIONS); \ + ASSERT_CHECK_VALUE_TYPE(env, udpSetExtraOptions, napi_function); \ + \ + napi_value udpOn = NapiUtils::GetNamedProperty(env, udpThis, SocketModuleExports::UDPSocket::FUNCTION_ON); \ + ASSERT_CHECK_VALUE_TYPE(env, udpOn, napi_function); \ + \ + napi_value udpOff = NapiUtils::GetNamedProperty(env, udpThis, SocketModuleExports::UDPSocket::FUNCTION_OFF); \ + ASSERT_CHECK_VALUE_TYPE(env, udpOff, napi_function); + +#define MAKE_ON_MESSAGE(FUNC_NAME) \ + [](napi_env env, napi_callback_info info) -> napi_value { \ + NETSTACK_LOGI("%s", FUNC_NAME); \ + \ + napi_value thisVal = nullptr; \ + size_t paramsCount = 1; \ + napi_value params[1] = {nullptr}; \ + NAPI_CALL(env, napi_get_cb_info(env, info, ¶msCount, params, &thisVal, nullptr)); \ + \ + napi_value remoteInfo = NapiUtils::GetNamedProperty(env, params[0], KEY_REMOTE_INFO); \ + NETSTACK_LOGI("On recv message"); \ + NETSTACK_LOGI("address: %s", NapiUtils::GetStringPropertyUtf8(env, remoteInfo, KEY_ADDRESS).c_str()); \ + NETSTACK_LOGI("port: %u", NapiUtils::GetUint32Property(env, remoteInfo, KEY_PORT)); \ + NETSTACK_LOGI("size: %u", NapiUtils::GetUint32Property(env, remoteInfo, KEY_SIZE)); \ + \ + napi_value msgBuffer = NapiUtils::GetNamedProperty(env, params[0], KEY_MESSAGE); \ + size_t len = 0; \ + void *data = NapiUtils::GetInfoFromArrayBufferValue(env, msgBuffer, &len); \ + std::string s; \ + s.append((char *)data, len); \ + NETSTACK_LOGI("data:\n%s", s.c_str()); \ + \ + NETSTACK_LOGI("\n\n\n"); \ + return NapiUtils::GetUndefined(env); \ + } + +#define TEST_TCP(TEST_NAME, LOCAL_IP, REMOTE_IP, FAMILY, MAKER, PNG) \ + [[maybe_unused]] HWTEST_F(NativeEngineTest, TEST_NAME, testing::ext::TestSize.Level0) /* NOLINT */ \ + { \ + TCP_COMMON_DEFINES \ + \ + napi_value tcpBindAddress = NapiUtils::CreateObject(env); \ + NapiUtils::SetStringPropertyUtf8(env, (napi_value)tcpBindAddress, KEY_ADDRESS, LOCAL_IP); \ + NapiUtils::SetUint32Property(env, tcpBindAddress, KEY_FAMILY, (uint32_t)NetAddress::Family::FAMILY); \ + NapiUtils::SetUint32Property(env, tcpBindAddress, KEY_PORT, 5126); \ + \ + napi_value tcpConnectAddress = NapiUtils::CreateObject(env); \ + NapiUtils::SetStringPropertyUtf8(env, (napi_value)tcpConnectAddress, KEY_ADDRESS, REMOTE_IP); \ + NapiUtils::SetUint32Property(env, tcpConnectAddress, KEY_FAMILY, (uint32_t)NetAddress::Family::FAMILY); \ + NapiUtils::SetUint32Property(env, tcpConnectAddress, KEY_PORT, 1314); \ + \ + napi_value tcpConnectOptions = NapiUtils::CreateObject(env); \ + NapiUtils::SetNamedProperty(env, (napi_value)tcpConnectOptions, KEY_ADDRESS, tcpConnectAddress); \ + \ + const char *sendStr = nullptr; \ + size_t len = 0; \ + if (!PNG) { \ + sendStr = "Hello This is Tcp Test" #TEST_NAME; \ + len = strlen(sendStr); \ + } else { \ + FILE *fp = fopen("for-post.png", "rb"); \ + fseek(fp, 0L, SEEK_END); \ + long size = ftell(fp); \ + void *buffer = malloc(size); \ + fseek(fp, 0, SEEK_SET); \ + size_t readSize = fread((void *)buffer, 1, size, fp); \ + NETSTACK_LOGI("file size = %ld read size = %zu", size, readSize); \ + \ + sendStr = (const char *)buffer; \ + len = readSize; \ + } \ + \ + void *data = nullptr; \ + napi_value msgBuffer = NapiUtils::CreateArrayBuffer(env, len, &data); \ + memcpy_s(data, (size_t)len, sendStr, (size_t)len); \ + napi_value tcpSendOptions = NapiUtils::CreateObject(env); \ + NapiUtils::SetNamedProperty(env, (napi_value)tcpSendOptions, KEY_DATA, msgBuffer); \ + \ + napi_value event = NapiUtils::CreateStringUtf8(env, EVENT_MESSAGE); \ + napi_value eventCallback = NapiUtils::CreateFunction(env, #TEST_NAME, MAKER(#TEST_NAME), nullptr); \ + napi_value arg[2] = {event, eventCallback}; \ + NapiUtils::CallFunction(env, tcpThis, tcpOn, 2, arg); \ + \ + NapiUtils::CallFunction(env, tcpThis, tcpBind, 1, &tcpBindAddress); \ + \ + NapiUtils::CallFunction(env, tcpThis, tcpConnect, 1, &tcpConnectOptions); \ + \ + NapiUtils::CallFunction(env, tcpThis, tcpSend, 1, &tcpSendOptions); \ + \ + NapiUtils::CallFunction(env, tcpThis, tcpClose, 0, nullptr); \ + } + +#define TEST_UDP(TEST_NAME, LOCAL_IP, REMOTE_IP, FAMILY, MAKER, PNG) \ + [[maybe_unused]] HWTEST_F(NativeEngineTest, TEST_NAME, testing::ext::TestSize.Level0) /* NOLINT */ \ + { \ + UDP_COMMON_DEFINES \ + \ + napi_value udpBindAddress = NapiUtils::CreateObject(env); \ + NapiUtils::SetStringPropertyUtf8(env, (napi_value)udpBindAddress, KEY_ADDRESS, LOCAL_IP); \ + NapiUtils::SetUint32Property(env, udpBindAddress, KEY_FAMILY, (uint32_t)NetAddress::Family::FAMILY); \ + NapiUtils::SetUint32Property(env, udpBindAddress, KEY_PORT, 5126); \ + \ + napi_value udpSendAddress = NapiUtils::CreateObject(env); \ + NapiUtils::SetStringPropertyUtf8(env, (napi_value)udpSendAddress, KEY_ADDRESS, REMOTE_IP); \ + NapiUtils::SetUint32Property(env, udpSendAddress, KEY_FAMILY, (uint32_t)NetAddress::Family::FAMILY); \ + NapiUtils::SetUint32Property(env, udpSendAddress, KEY_PORT, 4556); \ + \ + const char *sendStr = nullptr; \ + size_t len = 0; \ + if (!PNG) { \ + sendStr = "Hello UDP UDP Test" #TEST_NAME; \ + len = strlen(sendStr); \ + } else { \ + FILE *fp = fopen("for-post.png", "rb"); \ + fseek(fp, 0L, SEEK_END); \ + long size = ftell(fp); \ + void *buffer = malloc(size); \ + fseek(fp, 0, SEEK_SET); \ + size_t readSize = fread((void *)buffer, 1, size, fp); \ + NETSTACK_LOGI("file size = %ld read size = %zu", size, readSize); \ + \ + sendStr = (const char *)buffer; \ + len = readSize; \ + } \ + \ + void *data = nullptr; \ + napi_value msgBuffer = NapiUtils::CreateArrayBuffer(env, len, &data); \ + memcpy_s(data, len, sendStr, len); \ + \ + napi_value udpSendOptions = NapiUtils::CreateObject(env); \ + NapiUtils::SetNamedProperty(env, (napi_value)udpSendOptions, KEY_ADDRESS, udpSendAddress); \ + NapiUtils::SetNamedProperty(env, (napi_value)udpSendOptions, KEY_DATA, msgBuffer); \ + \ + napi_value event = NapiUtils::CreateStringUtf8(env, EVENT_MESSAGE); \ + napi_value eventCallback = NapiUtils::CreateFunction(env, #TEST_NAME, MAKER(#TEST_NAME), nullptr); \ + napi_value arg[2] = {event, eventCallback}; \ + NapiUtils::CallFunction(env, udpThis, udpOn, 2, arg); \ + \ + NapiUtils::CallFunction(env, udpThis, udpBind, 1, &udpBindAddress); \ + \ + napi_value extraOptions = NapiUtils::CreateObject(env); \ + NapiUtils::SetUint32Property(env, extraOptions, KEY_RECEIVE_BUFFER_SIZE, 1024); \ + NapiUtils::SetUint32Property(env, extraOptions, KEY_SEND_BUFFER_SIZE, 1024); \ + NapiUtils::CallFunction(env, udpThis, udpSetExtraOptions, 1, &extraOptions); \ + \ + NapiUtils::CallFunction(env, udpThis, udpSend, 1, &udpSendOptions); \ + \ + NapiUtils::CallFunction(env, udpThis, udpClose, 0, nullptr); \ + } + +#define MAKE_PNG_ON_MESSAGE(FUNC_NAME) \ + [](napi_env env, napi_callback_info info) -> napi_value { \ + NETSTACK_LOGI("%s", FUNC_NAME); \ + \ + napi_value thisVal = nullptr; \ + size_t paramsCount = 1; \ + napi_value params[1] = {nullptr}; \ + NAPI_CALL(env, napi_get_cb_info(env, info, ¶msCount, params, &thisVal, nullptr)); \ + \ + napi_value remoteInfo = NapiUtils::GetNamedProperty(env, params[0], KEY_REMOTE_INFO); \ + NETSTACK_LOGI("On recv message"); \ + NETSTACK_LOGI("address: %s", NapiUtils::GetStringPropertyUtf8(env, remoteInfo, KEY_ADDRESS).c_str()); \ + NETSTACK_LOGI("port: %u", NapiUtils::GetUint32Property(env, remoteInfo, KEY_PORT)); \ + NETSTACK_LOGI("size: %u", NapiUtils::GetUint32Property(env, remoteInfo, KEY_SIZE)); \ + \ + napi_value msgBuffer = NapiUtils::GetNamedProperty(env, params[0], KEY_MESSAGE); \ + size_t len = 0; \ + void *data = NapiUtils::GetInfoFromArrayBufferValue(env, msgBuffer, &len); \ + std::string s; \ + \ + FILE *fp = fopen(FUNC_NAME ".png", "ab"); \ + if (fp != nullptr) { \ + \ + fwrite(data, 1, len, fp); \ + fclose(fp); \ + } \ + \ + NETSTACK_LOGI("\n\n\n"); \ + return NapiUtils::GetUndefined(env); \ + } + +namespace OHOS::NetStack { +TEST_TCP(TEST_TCP1, LOCAL_IPV4_IP, REMOTE_IPV4_IP, IPv4, MAKE_ON_MESSAGE, false) +TEST_TCP(TEST_TCP2, LOCAL_IPV4_IP, REMOTE_IPV4_IP, IPv4, MAKE_ON_MESSAGE, false) +TEST_TCP(TEST_TCP3, LOCAL_IPV4_IP, REMOTE_IPV4_IP, IPv4, MAKE_ON_MESSAGE, false) +TEST_TCP(TEST_TCP4, LOCAL_IPV4_IP, REMOTE_IPV4_IP, IPv4, MAKE_ON_MESSAGE, false) +TEST_UDP(TEST_UDP1, LOCAL_IPV4_IP, REMOTE_IPV4_IP, IPv4, MAKE_ON_MESSAGE, false) +TEST_UDP(TEST_UDP2, LOCAL_IPV4_IP, REMOTE_IPV4_IP, IPv4, MAKE_ON_MESSAGE, false) +TEST_UDP(TEST_UDP3, LOCAL_IPV4_IP, REMOTE_IPV4_IP, IPv4, MAKE_ON_MESSAGE, false) +TEST_UDP(TEST_UDP4, LOCAL_IPV4_IP, REMOTE_IPV4_IP, IPv4, MAKE_ON_MESSAGE, false) + +TEST_TCP(TEST_TCP1_IPv6, LOCAL_IPV6_IP, REMOTE_IPV6_IP, IPv6, MAKE_ON_MESSAGE, false) +TEST_TCP(TEST_TCP2_IPv6, LOCAL_IPV6_IP, REMOTE_IPV6_IP, IPv6, MAKE_ON_MESSAGE, false) +TEST_TCP(TEST_TCP3_IPv6, LOCAL_IPV6_IP, REMOTE_IPV6_IP, IPv6, MAKE_ON_MESSAGE, false) +TEST_TCP(TEST_TCP4_IPv6, LOCAL_IPV6_IP, REMOTE_IPV6_IP, IPv6, MAKE_ON_MESSAGE, false) +TEST_UDP(TEST_UDP1_IPv6, LOCAL_IPV6_IP, REMOTE_IPV6_IP, IPv6, MAKE_ON_MESSAGE, false) +TEST_UDP(TEST_UDP2_IPv6, LOCAL_IPV6_IP, REMOTE_IPV6_IP, IPv6, MAKE_ON_MESSAGE, false) +TEST_UDP(TEST_UDP3_IPv6, LOCAL_IPV6_IP, REMOTE_IPV6_IP, IPv6, MAKE_ON_MESSAGE, false) +TEST_UDP(TEST_UDP4_IPv6, LOCAL_IPV6_IP, REMOTE_IPV6_IP, IPv6, MAKE_ON_MESSAGE, false) + +TEST_TCP(TEST_TCP1_PNG, LOCAL_IPV4_IP, REMOTE_IPV4_IP, IPv4, MAKE_PNG_ON_MESSAGE, true) +TEST_TCP(TEST_TCP2_PNG, LOCAL_IPV4_IP, REMOTE_IPV4_IP, IPv4, MAKE_PNG_ON_MESSAGE, true) +TEST_TCP(TEST_TCP3_PNG, LOCAL_IPV4_IP, REMOTE_IPV4_IP, IPv4, MAKE_PNG_ON_MESSAGE, true) +TEST_TCP(TEST_TCP4_PNG, LOCAL_IPV4_IP, REMOTE_IPV4_IP, IPv4, MAKE_PNG_ON_MESSAGE, true) +TEST_UDP(TEST_UDP1_PNG, LOCAL_IPV4_IP, REMOTE_IPV4_IP, IPv4, MAKE_PNG_ON_MESSAGE, true) +TEST_UDP(TEST_UDP2_PNG, LOCAL_IPV4_IP, REMOTE_IPV4_IP, IPv4, MAKE_PNG_ON_MESSAGE, true) +TEST_UDP(TEST_UDP3_PNG, LOCAL_IPV4_IP, REMOTE_IPV4_IP, IPv4, MAKE_PNG_ON_MESSAGE, true) +TEST_UDP(TEST_UDP4_PNG, LOCAL_IPV4_IP, REMOTE_IPV4_IP, IPv4, MAKE_PNG_ON_MESSAGE, true) + +TEST_TCP(TEST_TCP1_IPv6_PNG, LOCAL_IPV6_IP, REMOTE_IPV6_IP, IPv6, MAKE_PNG_ON_MESSAGE, true) +TEST_TCP(TEST_TCP2_IPv6_PNG, LOCAL_IPV6_IP, REMOTE_IPV6_IP, IPv6, MAKE_PNG_ON_MESSAGE, true) +TEST_TCP(TEST_TCP3_IPv6_PNG, LOCAL_IPV6_IP, REMOTE_IPV6_IP, IPv6, MAKE_PNG_ON_MESSAGE, true) +TEST_TCP(TEST_TCP4_IPv6_PNG, LOCAL_IPV6_IP, REMOTE_IPV6_IP, IPv6, MAKE_PNG_ON_MESSAGE, true) +TEST_UDP(TEST_UDP1_IPv6_PNG, LOCAL_IPV6_IP, REMOTE_IPV6_IP, IPv6, MAKE_PNG_ON_MESSAGE, true) +TEST_UDP(TEST_UDP2_IPv6_PNG, LOCAL_IPV6_IP, REMOTE_IPV6_IP, IPv6, MAKE_PNG_ON_MESSAGE, true) +TEST_UDP(TEST_UDP3_IPv6_PNG, LOCAL_IPV6_IP, REMOTE_IPV6_IP, IPv6, MAKE_PNG_ON_MESSAGE, true) +TEST_UDP(TEST_UDP4_IPv6_PNG, LOCAL_IPV6_IP, REMOTE_IPV6_IP, IPv6, MAKE_PNG_ON_MESSAGE, true) + +} // namespace OHOS::NetStack + +int main(int argc, char **argv) +{ + testing::GTEST_FLAG(output) = "xml:./"; + testing::InitGoogleTest(&argc, argv); + + JSRuntime *rt = JS_NewRuntime(); + + if (rt == nullptr) { + return 0; + } + + JSContext *ctx = JS_NewContext(rt); + if (ctx == nullptr) { + return 0; + } + + js_std_add_helpers(ctx, 0, nullptr); + + g_nativeEngine = new QuickJSNativeEngine(rt, ctx, nullptr); // default instance id 0 + + int ret = RUN_ALL_TESTS(); + (void)ret; + + g_nativeEngine->Loop(LOOP_DEFAULT); + /* NETSTACK_LOGI("test all number %u", g_testNum); + for (int i = 0; i < g_testNum; ++i) { + g_nativeEngine->Loop(LOOP_ONCE); + } */ + + return 0; +} \ No newline at end of file diff --git a/utils/BUILD.gn b/utils/CMakeLists.txt similarity index 37% rename from utils/BUILD.gn rename to utils/CMakeLists.txt index 5936d280498f6ec4c04e6e3005b5602e4c367dba..d8c48749b512dda5efc4b1d8e01940df208aab8e 100644 --- a/utils/BUILD.gn +++ b/utils/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2021 Huawei Device Co., Ltd. +# Copyright (C) 2021-2022 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 @@ -11,51 +11,13 @@ # See the License for the specific language governing permissions and # limitations under the License. -import("//build/ohos.gni") - -group("common_target") { - deps = [ ":net_manager_common" ] -} - -config("netmgr_common_config") { - include_dirs = [ - "log/include", - ] -} - -ohos_shared_library("net_manager_common") { - sources = [ - "log/src/netmgr_log_wrapper.cpp" - ] - - defines = [ - "NET_MANAGER_LOG_TAG = \"NetMgrCommon\"", - "LOG_DOMAIN = 0xD0015B0", - ] - - if (is_standard_system) { - defines += [ "STANDARD_SYSTEM_ENABLE" ] - } - - public_configs = [ - ":netmgr_common_config", - "//utils/native/base:utils_config", - ] - - public_deps = [ - "//utils/native/base:utils" - ] - - if (is_double_framework) { - cflags_cc = [ "-DCONFIG_DUAL_FRAMEWORK" ] - } - - if (is_standard_system) { - external_deps = [ "hiviewdfx_hilog_native:libhilog" ] - } else { - external_deps = [ "hilog:libhilog" ] - } - - part_name = "netstack" - subsystem_name = "communication" -} +add_library( + netstack_utils + SHARED + common_utils/src/netstack_common_utils.cpp + napi_utils/src/netstack_napi_utils.cpp + event_manager/src/netstack_event_listener.cpp + event_manager/src/netstack_event_manager.cpp + base_context/src/netstack_base_context.cpp + module_template/src/netstack_module_template.cpp +) \ No newline at end of file diff --git a/utils/base_async_work/include/netstack_base_async_work.h b/utils/base_async_work/include/netstack_base_async_work.h new file mode 100644 index 0000000000000000000000000000000000000000..f864d3a305b1614ed0416be63da3952d12e975d9 --- /dev/null +++ b/utils/base_async_work/include/netstack_base_async_work.h @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2021-2022 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_NETSTACK_BASE_ASYNC_WORK_H +#define COMMUNICATIONNETSTACK_NETSTACK_BASE_ASYNC_WORK_H + +#include "napi/native_api.h" +#include "napi/native_node_api.h" +#include "netstack_base_context.h" +#include "netstack_napi_utils.h" +#include "noncopyable.h" +#include + +#define PARSE_PARAM_FAILED -1 + +#define BUSINESS_ERROR_KEY "code" + +namespace OHOS::NetStack { + +class BaseAsyncWork final { +public: + ACE_DISALLOW_COPY_AND_MOVE(BaseAsyncWork); + + BaseAsyncWork() = delete; + + template static void ExecAsyncWork(napi_env env, void *data) + { + static_assert(std::is_base_of::value); + + (void)env; + + auto context = static_cast(data); + if (!context->IsParseOK()) { + context->SetErrorCode(PARSE_PARAM_FAILED); + return; + } + + if (Executor != nullptr) { + context->SetExecOK(Executor(context)); + } + /* do not have async executor, execOK should be set in sync work */ + } + + template + static void AsyncWorkCallback(napi_env env, napi_status status, void *data) + { + static_assert(std::is_base_of::value); + + if (status != napi_ok) { + return; + } + auto deleter = [](Context *context) { delete context; }; + std::unique_ptr context(static_cast(data), deleter); + size_t argc = 2; + napi_value argv[2] = {nullptr}; + if (context->IsExecOK()) { + argv[0] = NapiUtils::GetUndefined(env); + + if (Callback != nullptr) { + argv[1] = Callback(context.get()); + } else { + argv[1] = NapiUtils::GetUndefined(env); + } + if (argv[1] == nullptr) { + return; + } + } else { + argv[0] = NapiUtils::CreateObject(env); + if (argv[0] == nullptr) { + return; + } + NapiUtils::SetInt32Property(env, argv[0], BUSINESS_ERROR_KEY, context->GetErrorCode()); + + argv[1] = NapiUtils::GetUndefined(env); + } + + if (context->GetDeferred() != nullptr) { + if (context->IsExecOK()) { + napi_resolve_deferred(env, context->GetDeferred(), argv[1]); + } else { + napi_reject_deferred(env, context->GetDeferred(), argv[0]); + } + return; + } + + napi_value func = context->GetCallback(); + napi_value undefined = NapiUtils::GetUndefined(env); + (void)NapiUtils::CallFunction(env, undefined, func, argc, argv); + } +}; +} // namespace OHOS::NetStack + +#endif /* COMMUNICATIONNETSTACK_NETSTACK_BASE_ASYNC_WORK_H */ diff --git a/utils/base_context/include/netstack_base_context.h b/utils/base_context/include/netstack_base_context.h new file mode 100644 index 0000000000000000000000000000000000000000..c80407ce05159f783aeef558d0770f807266f891 --- /dev/null +++ b/utils/base_context/include/netstack_base_context.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2021-2022 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_BASE_CONTEXT_H +#define COMMUNICATIONNETSTACK_BASE_CONTEXT_H + +#include "napi/native_api.h" +#include "napi/native_node_api.h" +#include "netstack_event_manager.h" +#include "noncopyable.h" +#include + +namespace OHOS::NetStack { + +typedef void (*AsyncWorkExecutor)(napi_env env, void *data); + +typedef void (*AsyncWorkCallback)(napi_env env, napi_status status, void *data); + +class BaseContext { +public: + ACE_DISALLOW_COPY_AND_MOVE(BaseContext); + + BaseContext() = delete; + + explicit BaseContext(napi_env env, EventManager *manager); + + virtual ~BaseContext(); + + void SetParseOK(bool parseOK); + + void SetExecOK(bool requestOK); + + void SetErrorCode(int32_t errorCode); + + napi_status SetCallback(napi_value callback); + + void DeleteCallback(); + + void CreateAsyncWork(const std::string &name, AsyncWorkExecutor executor, AsyncWorkCallback callback); + + void DeleteAsyncWork(); + + napi_value CreatePromise(); + + [[nodiscard]] bool IsParseOK() const; + + [[nodiscard]] bool IsExecOK() const; + + [[nodiscard]] napi_env GetEnv() const; + + [[nodiscard]] int32_t GetErrorCode() const; + + [[nodiscard]] napi_value GetCallback() const; + + [[nodiscard]] napi_deferred GetDeferred() const; + + [[nodiscard]] const std::string &GetAsyncWorkName() const; + + void Emit(const std::string &type, const std::pair &argv); + +protected: + EventManager *manager_; + +private: + napi_env env_; + + bool parseOK_; + + bool requestOK_; + + int32_t errorCode_; + + napi_ref callback_; + + napi_async_work asyncWork_; + + napi_deferred deferred_; + + std::string asyncWorkName_; +}; + +} // namespace OHOS::NetStack + +#endif /* COMMUNICATIONNETSTACK_BASE_CONTEXT_H */ diff --git a/utils/base_context/src/netstack_base_context.cpp b/utils/base_context/src/netstack_base_context.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b94055ca36322fbcb7b19ee59f61dd8beb25768a --- /dev/null +++ b/utils/base_context/src/netstack_base_context.cpp @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2021-2022 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 "netstack_base_context.h" + +#include "netstack_napi_utils.h" + +namespace OHOS::NetStack { + +BaseContext::BaseContext(napi_env env, EventManager *manager) + : manager_(manager), + env_(env), + parseOK_(false), + requestOK_(false), + errorCode_(0), + callback_(nullptr), + asyncWork_(nullptr), + deferred_(nullptr) +{ +} + +BaseContext::~BaseContext() +{ + DeleteCallback(); + DeleteAsyncWork(); +} + +void BaseContext::SetParseOK(bool parseOK) +{ + parseOK_ = parseOK; +} + +void BaseContext::SetExecOK(bool requestOK) +{ + requestOK_ = requestOK; +} + +void BaseContext::SetErrorCode(int32_t errorCode) +{ + errorCode_ = errorCode; +} + +napi_status BaseContext::SetCallback(napi_value callback) +{ + if (callback_ != nullptr) { + (void)napi_delete_reference(env_, callback_); + } + return napi_create_reference(env_, callback, 1, &callback_); +} + +void BaseContext::DeleteCallback() +{ + if (callback_ == nullptr) { + return; + } + (void)napi_delete_reference(env_, callback_); + callback_ = nullptr; +} + +void BaseContext::CreateAsyncWork(const std::string &name, AsyncWorkExecutor executor, AsyncWorkCallback callback) +{ + napi_status ret = napi_create_async_work(env_, nullptr, NapiUtils::CreateStringUtf8(env_, name), executor, callback, + this, &asyncWork_); + if (ret != napi_ok) { + return; + } + asyncWorkName_ = name; + (void)napi_queue_async_work(env_, asyncWork_); +} + +void BaseContext::DeleteAsyncWork() +{ + if (asyncWork_ == nullptr) { + return; + } + (void)napi_delete_async_work(env_, asyncWork_); +} + +napi_value BaseContext::CreatePromise() +{ + napi_value result = nullptr; + NAPI_CALL(env_, napi_create_promise(env_, &deferred_, &result)); + return result; +} + +bool BaseContext::IsParseOK() const +{ + return parseOK_; +} + +bool BaseContext::IsExecOK() const +{ + return requestOK_; +} + +napi_env BaseContext::GetEnv() const +{ + return env_; +} + +int32_t BaseContext::GetErrorCode() const +{ + return errorCode_; +} + +napi_value BaseContext::GetCallback() const +{ + if (callback_ == nullptr) { + return nullptr; + } + napi_value callback = nullptr; + NAPI_CALL(env_, napi_get_reference_value(env_, callback_, &callback)); + return callback; +} + +napi_deferred BaseContext::GetDeferred() const +{ + return deferred_; +} + +const std::string &BaseContext::GetAsyncWorkName() const +{ + return asyncWorkName_; +} + +void BaseContext::Emit(const std::string &type, const std::pair &argv) +{ + if (manager_ != nullptr) { + manager_->Emit(type, argv); + } +} + +} // namespace OHOS::NetStack \ No newline at end of file diff --git a/frameworks/js/napi/socket/include/netaddress.h b/utils/common_utils/include/netstack_common_utils.h similarity index 55% rename from frameworks/js/napi/socket/include/netaddress.h rename to utils/common_utils/include/netstack_common_utils.h index 884fbb77b176e763f2141cce133f97508fa1bf00..fb87158fe00b3cf91d88ffcda41f0aa209e2fdad 100644 --- a/frameworks/js/napi/socket/include/netaddress.h +++ b/utils/common_utils/include/netstack_common_utils.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Huawei Device Co., Ltd. + * Copyright (C) 2021-2022 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 @@ -13,22 +13,20 @@ * limitations under the License. */ -#ifndef NETADDRESS_H -#define NETADDRESS_H - -#include "napi/native_api.h" -#include "napi/native_node_api.h" +#ifndef COMMUNICATIONNETSTACK_COMMON_UTILS_H +#define COMMUNICATIONNETSTACK_COMMON_UTILS_H #include +#include + +namespace OHOS::NetStack::CommonUtils { + +std::vector Split(const std::string &str, const std::string &sep); + +std::string Strip(const std::string &str, char ch = ' '); + +std::string ToLower(const std::string &s); + +} // namespace OHOS::NetStack::CommonUtils -namespace OHOS { -namespace NetManagerStandard { -enum SocketFamily { IPV4 = 1, IPV6 = 2 }; -struct NetAddress { - std::string ipAddress = ""; - int32_t family = 1; // IPv4 = 1; IPv6 = 2, default is IPv4 - int32_t port = 8080; // [0, 65535] -}; -} // namespace NetManagerStandard -} // namespace OHOS -#endif // NETADDRESS_H \ No newline at end of file +#endif /* COMMUNICATIONNETSTACK_COMMON_UTILS_H */ diff --git a/utils/common_utils/src/netstack_common_utils.cpp b/utils/common_utils/src/netstack_common_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5d1c20eee788060e8ad83c04bdea5d1b5687b6bd --- /dev/null +++ b/utils/common_utils/src/netstack_common_utils.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2021-2022 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 "netstack_common_utils.h" + +#include + +namespace OHOS::NetStack::CommonUtils { + +std::vector Split(const std::string &str, const std::string &sep) +{ + std::string s = str; + std::vector res; + while (!s.empty()) { + size_t pos = s.find(sep); + if (pos == std::string::npos) { + res.emplace_back(s); + break; + } + res.emplace_back(s.substr(0, pos)); + s = s.substr(pos + sep.size()); + } + return res; +} + +std::string Strip(const std::string &str, char ch) +{ + int64_t i = 0; + while (i < str.size() && str[i] == ch) { + ++i; + } + int64_t j = static_cast(str.size()) - 1; + while (j > 0 && str[j] == ch) { + --j; + } + if (i >= 0 && i < str.size() && j >= 0 && j < str.size() && j - i + 1 > 0) { + return str.substr(i, j - i + 1); + } + return ""; +} + +std::string ToLower(const std::string &s) +{ + std::string res = s; + std::transform(res.begin(), res.end(), res.begin(), tolower); + return res; +} + +} // namespace OHOS::NetStack::CommonUtils \ No newline at end of file diff --git a/utils/event_manager/include/netstack_event_listener.h b/utils/event_manager/include/netstack_event_listener.h new file mode 100644 index 0000000000000000000000000000000000000000..ff17def3e3a1fa06c17ce69cf8ca1ee92c3e19f1 --- /dev/null +++ b/utils/event_manager/include/netstack_event_listener.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2021-2022 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_EVENT_LISTENER_H +#define COMMUNICATIONNETSTACK_EVENT_LISTENER_H + +#include "napi/native_api.h" +#include "noncopyable.h" +#include + +namespace OHOS::NetStack { + +class EventListener { +public: + EventListener() = delete; + + EventListener(const EventListener &listener); + + EventListener(napi_env env, std::string type, napi_value callback, bool once, bool asyncCallback); + + ~EventListener(); + + EventListener &operator=(const EventListener &listener); + + void Emit(const std::string &eventType, size_t argc, napi_value *argv) const; + + [[nodiscard]] bool Match(const std::string &type, napi_value callback) const; + + [[nodiscard]] bool MatchOnce(const std::string &type) const; + + [[nodiscard]] bool IsAsyncCallback() const; + +private: + napi_env env_; + + std::string type_; + + bool once_; + + napi_ref callbackRef_; + + bool asyncCallback_; +}; + +} // namespace OHOS::NetStack + +#endif /* COMMUNICATIONNETSTACK_EVENT_LISTENER_H */ diff --git a/utils/event_manager/include/netstack_event_manager.h b/utils/event_manager/include/netstack_event_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..311fd7a65dc50885afe0aabc3f40b639879bb45b --- /dev/null +++ b/utils/event_manager/include/netstack_event_manager.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2021-2022 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_EVENT_MANAGER_H +#define COMMUNICATIONNETSTACK_EVENT_MANAGER_H + +#include "netstack_event_listener.h" +#include +#include + +namespace OHOS::NetStack { + +class EventManager { +public: + EventManager(); + + void AddListener(napi_env env, const std::string &type, napi_value callback, bool once, bool asyncCallback); + + void DeleteListener(const std::string &type, napi_value callback); + + void Emit(const std::string &type, const std::pair &argv); + + void SetData(void *data); + + [[nodiscard]] void *GetData(); + +private: + std::mutex mutex_; + + std::list listeners_; + + void *data_; +}; + +} // namespace OHOS::NetStack +#endif /* COMMUNICATIONNETSTACK_EVENT_MANAGER_H */ diff --git a/utils/event_manager/src/netstack_event_listener.cpp b/utils/event_manager/src/netstack_event_listener.cpp new file mode 100644 index 0000000000000000000000000000000000000000..94c961609b03bf08c721eed3ca2191ee02805fc0 --- /dev/null +++ b/utils/event_manager/src/netstack_event_listener.cpp @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2021-2022 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 "netstack_event_listener.h" + +#include "netstack_napi_utils.h" + +namespace OHOS::NetStack { + +EventListener::EventListener(napi_env env, std::string type, napi_value callback, bool once, bool asyncCallback) + : env_(env), + type_(std::move(type)), + once_(once), + callbackRef_(NapiUtils::CreateReference(env, callback)), + asyncCallback_(asyncCallback) +{ +} + +EventListener::EventListener(const EventListener &listener) +{ + env_ = listener.env_; + type_ = listener.type_; + once_ = listener.once_; + asyncCallback_ = listener.asyncCallback_; + + if (listener.callbackRef_ == nullptr) { + callbackRef_ = nullptr; + return; + } + napi_value callback = NapiUtils::GetReference(listener.env_, listener.callbackRef_); + callbackRef_ = NapiUtils::CreateReference(env_, callback); +} + +EventListener::~EventListener() +{ + if (callbackRef_ != nullptr) { + NapiUtils::DeleteReference(env_, callbackRef_); + } + callbackRef_ = nullptr; +} + +EventListener &EventListener::operator=(const EventListener &listener) +{ + env_ = listener.env_; + type_ = listener.type_; + once_ = listener.once_; + asyncCallback_ = listener.asyncCallback_; + + if (listener.callbackRef_ == nullptr) { + callbackRef_ = nullptr; + return *this; + } + napi_value callback = NapiUtils::GetReference(listener.env_, listener.callbackRef_); + callbackRef_ = NapiUtils::CreateReference(env_, callback); + return *this; +} + +void EventListener::Emit(const std::string &eventType, size_t argc, napi_value *argv) const +{ + if (type_ != eventType) { + return; + } + + if (callbackRef_ == nullptr) { + return; + } + napi_value callback = NapiUtils::GetReference(env_, callbackRef_); + if (NapiUtils::GetValueType(env_, callback) == napi_function) { + (void)NapiUtils::CallFunction(env_, NapiUtils::GetUndefined(env_), callback, argc, argv); + } +} + +bool EventListener::Match(const std::string &type, napi_value callback) const +{ + if (type_ != type) { + return false; + } + + napi_value callback1 = NapiUtils::GetReference(env_, callbackRef_); + bool ret = false; + NAPI_CALL_BASE(env_, napi_strict_equals(env_, callback1, callback, &ret), false); + return ret; +} + +bool EventListener::MatchOnce(const std::string &type) const +{ + if (type_ != type) { + return false; + } + return once_; +} + +bool EventListener::IsAsyncCallback() const +{ + return asyncCallback_; +} + +} // namespace OHOS::NetStack diff --git a/utils/event_manager/src/netstack_event_manager.cpp b/utils/event_manager/src/netstack_event_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..77bb323ada7e7c02245f5a4648909f596e1a9ea3 --- /dev/null +++ b/utils/event_manager/src/netstack_event_manager.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2021-2022 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 "netstack_event_manager.h" + +#include + +namespace OHOS::NetStack { + +EventManager::EventManager() : data_(nullptr) {} + +void EventManager::AddListener(napi_env env, + const std::string &type, + napi_value callback, + bool once, + bool asyncCallback) +{ + listeners_.emplace_back(EventListener(env, type, callback, once, asyncCallback)); +} + +void EventManager::DeleteListener(const std::string &type, napi_value callback) +{ + std::lock_guard lock(mutex_); + auto it = + std::remove_if(listeners_.begin(), listeners_.end(), [type, callback](const EventListener &listener) -> bool { + return listener.Match(type, callback); + }); + listeners_.erase(it, listeners_.end()); +} + +void EventManager::Emit(const std::string &type, const std::pair &argv) +{ + std::lock_guard lock(mutex_); + + std::for_each(listeners_.begin(), listeners_.end(), [type, argv](const EventListener &listener) { + if (listener.IsAsyncCallback()) { + /* AsyncCallback(BusinessError error, T data) */ + napi_value arg[2] = {argv.first, argv.second}; + listener.Emit(type, 2, arg); + } else { + /* Callback(T data)*/ + napi_value arg[1] = {argv.second}; + listener.Emit(type, 1, arg); + } + }); + + auto it = std::remove_if(listeners_.begin(), listeners_.end(), + [type](const EventListener &listener) -> bool { return listener.MatchOnce(type); }); + listeners_.erase(it, listeners_.end()); +} + +void EventManager::SetData(void *data) +{ + std::lock_guard lock(mutex_); + data_ = data; +} + +void *EventManager::GetData() +{ + std::lock_guard lock(mutex_); + return data_; +} + +} // namespace OHOS::NetStack \ No newline at end of file diff --git a/utils/log/include/netmgr_log_wrapper.h b/utils/log/include/netmgr_log_wrapper.h deleted file mode 100644 index 1158f5d4f6a84ae2d70959c1d9865f158f3b67f8..0000000000000000000000000000000000000000 --- a/utils/log/include/netmgr_log_wrapper.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2021 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 NETMGR_LOG_WRAPPER_H -#define NETMGR_LOG_WRAPPER_H - -#include - -#include "hilog/log.h" - -namespace OHOS { -namespace NetManagerStandard { -enum class NetMgrLogLevel { - DEBUG = 0, - INFO, - WARN, - ERROR, - FATAL, -}; - -class NetMgrLogWrapper { -public: - static bool JudgeLevel(const NetMgrLogLevel &level); - - static void SetLogLevel(const NetMgrLogLevel &level) - { - level_ = level; - } - - static const NetMgrLogLevel &GetLogLevel() - { - return level_; - } - - static std::string GetBriefFileName(const std::string &file); - -private: - static NetMgrLogLevel level_; -}; - -#ifndef NETMGR_LOG_TAG -#define NETMGR_LOG_TAG "NetMgrSubsystem" -#endif - -static constexpr OHOS::HiviewDFX::HiLogLabel NET_MGR_LABEL = {LOG_CORE, LOG_DOMAIN, NETMGR_LOG_TAG}; - -#define PRINT_LOG(op, fmt, ...) \ - (void)OHOS::HiviewDFX::HiLog::op(NET_MGR_LABEL, "[%{public}s-(%{public}s:%{public}d)]" fmt, __FUNCTION__, \ - __FILE__, __LINE__, ##__VA_ARGS__) - -#define NETMGR_LOGD(fmt, ...) PRINT_LOG(Debug, fmt, ##__VA_ARGS__) -#define NETMGR_LOGE(fmt, ...) PRINT_LOG(Error, fmt, ##__VA_ARGS__) -#define NETMGR_LOGW(fmt, ...) PRINT_LOG(Warn, fmt, ##__VA_ARGS__) -#define NETMGR_LOGI(fmt, ...) PRINT_LOG(Info, fmt, ##__VA_ARGS__) -#define NETMGR_LOGF(fmt, ...) PRINT_LOG(Fatal, fmt, ##__VA_ARGS__) -} // namespace NetManagerStandard -} // namespace OHOS -#endif // NETMGR_LOG_WRAPPER_H \ No newline at end of file diff --git a/utils/log/include/netstack_log.h b/utils/log/include/netstack_log.h new file mode 100644 index 0000000000000000000000000000000000000000..328c9b1ac948a93bd8a8471d57add59dcaad6f96 --- /dev/null +++ b/utils/log/include/netstack_log.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2021-2022 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_NETSTACK_LOG +#define COMMUNICATIONNETSTACK_NETSTACK_LOG + +#include +#include + +#define __FILENAME__ strrchr(__FILE__, '/') + 1 + +#if !defined(_WIN32) && !defined(__APPLE__) + +#include "hilog/log.h" + +#define NETSTACK_LOG_TAG "NetMgrSubsystem" + +#define NETSTACK_LOG_DOMAIN 0xD0015B0 + +static constexpr OHOS::HiviewDFX::HiLogLabel NETSTACK_LOG_LABEL = {LOG_CORE, NETSTACK_LOG_DOMAIN, NETSTACK_LOG_TAG}; + +#define NETSTACK_HILOG_PRINT(Level, fmt, ...) \ + (void)OHOS::HiviewDFX::HiLog::Level(NETSTACK_LOG_LABEL, "NETSTACK [%{public}s %{public}d] " fmt, __FILENAME__, \ + __LINE__, ##__VA_ARGS__) + +#else + +#include +#include + +constexpr uint32_t NETSTACK_MAX_BUFFER_SIZE = 4096; + +static void NetStackStripFormatString(const std::string &prefix, std::string &str) +{ + for (auto pos = str.find(prefix, 0); pos != std::string::npos; pos = str.find(prefix, pos)) { + str.erase(pos, prefix.size()); + } +} + +static void NetStackPrintLog(const char *fmt, ...) +{ + std::string newFmt(fmt); + NetStackStripFormatString("{public}", newFmt); + NetStackStripFormatString("{private}", newFmt); + + va_list args; + va_start(args, fmt); + + char buf[NETSTACK_MAX_BUFFER_SIZE] = {"\0"}; + int ret = vsnprintf(buf, sizeof(buf) - 1, newFmt.c_str(), args); + if (ret < 0) { + return; + } + va_end(args); + + printf("%s\r\n", buf); + fflush(stdout); +} + +#define NETSTACK_HILOG_PRINT(Level, fmt, ...) \ + NetStackPrintLog("NETSTACK %s [%s %d] " fmt, #Level, __FILENAME__, __LINE__, ##__VA_ARGS__) + +#endif /* !defined(_WIN32) && !defined(__APPLE__) */ + +/* #define NETSTACK_LOGF(fmt, ...) NETSTACK_HILOG_PRINT(Debug, fmt, ##__VA_ARGS__) */ + +#define NETSTACK_LOGE(fmt, ...) NETSTACK_HILOG_PRINT(Error, fmt, ##__VA_ARGS__) + +/* #define NETSTACK_LOGW(fmt, ...) NETSTACK_HILOG_PRINT(Warn, fmt, ##__VA_ARGS__) */ + +#define NETSTACK_LOGI(fmt, ...) NETSTACK_HILOG_PRINT(Info, fmt, ##__VA_ARGS__) + +/* #define NETSTACK_LOGD(fmt, ...) NETSTACK_HILOG_PRINT(Fatal, fmt, ##__VA_ARGS__) */ + +#endif /* COMMUNICATIONNETSTACK_NETSTACK_LOG */ \ No newline at end of file diff --git a/utils/module_template/include/netstack_module_template.h b/utils/module_template/include/netstack_module_template.h new file mode 100644 index 0000000000000000000000000000000000000000..0682dcd2152d8a2bb881a3e4f0d38ea33d364ae9 --- /dev/null +++ b/utils/module_template/include/netstack_module_template.h @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2021-2022 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_NETSTACK_MODULE_TEMPLATE_H +#define COMMUNICATIONNETSTACK_NETSTACK_MODULE_TEMPLATE_H + +#include "netstack_base_async_work.h" +#include "netstack_base_context.h" +#include + +#define MAX_PARAM_NUM 64 + +namespace OHOS::NetStack::ModuleTemplate { + +typedef void (*Finalizer)(napi_env, void *data, void *); + +template +napi_value Interface(napi_env env, + napi_callback_info info, + const std::string &asyncWorkName, + bool (*Work)(napi_env, napi_value, Context *), + AsyncWorkExecutor executor, + AsyncWorkCallback callback) +{ + static_assert(std::is_base_of::value); + + napi_value thisVal = nullptr; + size_t paramsCount = MAX_PARAM_NUM; + napi_value params[MAX_PARAM_NUM] = {nullptr}; + NAPI_CALL(env, napi_get_cb_info(env, info, ¶msCount, params, &thisVal, nullptr)); + + EventManager *manager = nullptr; + napi_unwrap(env, thisVal, reinterpret_cast(&manager)); + + auto context = new Context(env, manager); + context->ParseParams(params, paramsCount); + if (Work != nullptr) { + if (!Work(env, thisVal, context)) { + NETSTACK_LOGE("work failed error code = %{public}d", context->GetErrorCode()); + } + } + + context->CreateAsyncWork(asyncWorkName, executor, callback); + if (NapiUtils::GetValueType(env, context->GetCallback()) != napi_function) { + return context->CreatePromise(); + } + return NapiUtils::GetUndefined(env); +} + +template +napi_value + InterfaceWithOutAsyncWork(napi_env env, napi_callback_info info, bool (*Work)(napi_env, napi_value, Context *)) +{ + static_assert(std::is_base_of::value); + + napi_value thisVal = nullptr; + size_t paramsCount = MAX_PARAM_NUM; + napi_value params[MAX_PARAM_NUM] = {nullptr}; + NAPI_CALL(env, napi_get_cb_info(env, info, ¶msCount, params, &thisVal, nullptr)); + + EventManager *manager = nullptr; + napi_unwrap(env, thisVal, reinterpret_cast(&manager)); + + auto context = new Context(env, manager); + context->ParseParams(params, paramsCount); + if (Work != nullptr) { + if (!Work(env, thisVal, context)) { + NETSTACK_LOGE("work failed error code = %{public}d", context->GetErrorCode()); + } + } + + if (NapiUtils::GetValueType(env, context->GetCallback()) != napi_function) { + return context->CreatePromise(); + } + return NapiUtils::GetUndefined(env); +} + +napi_value + On(napi_env env, napi_callback_info info, const std::initializer_list &events, bool asyncCallback); + +napi_value + Once(napi_env env, napi_callback_info info, const std::initializer_list &events, bool asyncCallback); + +napi_value Off(napi_env env, napi_callback_info info, const std::initializer_list &events); + +void DefineClass(napi_env env, + napi_value exports, + const std::initializer_list &properties, + const std::string &className); + +napi_value NewInstance(napi_env env, napi_callback_info info, const std::string &className, Finalizer finalizer); + +} // namespace OHOS::NetStack::ModuleTemplate +#endif /* COMMUNICATIONNETSTACK_NETSTACK_MODULE_TEMPLATE_H */ diff --git a/utils/module_template/src/netstack_module_template.cpp b/utils/module_template/src/netstack_module_template.cpp new file mode 100644 index 0000000000000000000000000000000000000000..263cda17abb86ef938817699e20c416a0f482fcf --- /dev/null +++ b/utils/module_template/src/netstack_module_template.cpp @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2021-2022 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 "netstack_module_template.h" + +#include + +namespace OHOS::NetStack::ModuleTemplate { + +napi_value + On(napi_env env, napi_callback_info info, const std::initializer_list &events, bool asyncCallback) +{ + napi_value thisVal = nullptr; + size_t paramsCount = 2; + napi_value params[2] = {nullptr}; + NAPI_CALL(env, napi_get_cb_info(env, info, ¶msCount, params, &thisVal, nullptr)); + + std::string event = NapiUtils::GetStringFromValueUtf8(env, params[0]); + if (paramsCount != 2 || std::find(events.begin(), events.end(), event) == events.end()) { + return NapiUtils::GetUndefined(env); + } + + EventManager *manager = nullptr; + napi_unwrap(env, thisVal, reinterpret_cast(&manager)); + if (manager != nullptr) { + manager->AddListener(env, event, params[1], false, asyncCallback); + } + + return NapiUtils::GetUndefined(env); +} + +napi_value + Once(napi_env env, napi_callback_info info, const std::initializer_list &events, bool asyncCallback) +{ + napi_value thisVal = nullptr; + size_t paramsCount = 2; + napi_value params[2] = {nullptr}; + NAPI_CALL(env, napi_get_cb_info(env, info, ¶msCount, params, &thisVal, nullptr)); + + std::string event = NapiUtils::GetStringFromValueUtf8(env, params[0]); + if (paramsCount != 2 || std::find(events.begin(), events.end(), event) == events.end()) { + return NapiUtils::GetUndefined(env); + } + + EventManager *manager = nullptr; + napi_unwrap(env, thisVal, reinterpret_cast(&manager)); + if (manager != nullptr) { + manager->AddListener(env, event, params[1], true, asyncCallback); + } + + return NapiUtils::GetUndefined(env); +} + +napi_value Off(napi_env env, napi_callback_info info, const std::initializer_list &events) +{ + napi_value thisVal = nullptr; + size_t paramsCount = 2; + napi_value params[2] = {nullptr}; + NAPI_CALL(env, napi_get_cb_info(env, info, ¶msCount, params, &thisVal, nullptr)); + + std::string event = NapiUtils::GetStringFromValueUtf8(env, params[0]); + if (paramsCount != 2 || std::find(events.begin(), events.end(), event) == events.end()) { + return NapiUtils::GetUndefined(env); + } + + EventManager *manager = nullptr; + napi_unwrap(env, thisVal, reinterpret_cast(&manager)); + if (manager != nullptr) { + manager->DeleteListener(event, params[1]); + } + + return NapiUtils::GetUndefined(env); +} + +void DefineClass(napi_env env, + napi_value exports, + const std::initializer_list &properties, + const std::string &className) +{ + auto constructor = [](napi_env env, napi_callback_info info) -> napi_value { + napi_value thisVal = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVal, nullptr)); + + return thisVal; + }; + + napi_value jsConstructor = nullptr; + + napi_property_descriptor descriptors[properties.size()]; + std::copy(properties.begin(), properties.end(), descriptors); + + NAPI_CALL_RETURN_VOID(env, napi_define_class(env, className.c_str(), NAPI_AUTO_LENGTH, constructor, nullptr, + properties.size(), descriptors, &jsConstructor)); + + NapiUtils::SetNamedProperty(env, exports, className, jsConstructor); +} + +napi_value NewInstance(napi_env env, napi_callback_info info, const std::string &className, Finalizer finalizer) +{ + napi_value thisVal = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVal, nullptr)); + + napi_value jsConstructor = NapiUtils::GetNamedProperty(env, thisVal, className); + if (NapiUtils::GetValueType(env, jsConstructor) == napi_undefined) { + return nullptr; + } + + napi_value result = nullptr; + NAPI_CALL(env, napi_new_instance(env, jsConstructor, 0, nullptr, &result)); + + auto manager = new EventManager(); + napi_wrap(env, result, reinterpret_cast(manager), finalizer, nullptr, nullptr); + + return result; +} + +} // namespace OHOS::NetStack::ModuleTemplate \ No newline at end of file diff --git a/utils/napi_utils/include/netstack_napi_utils.h b/utils/napi_utils/include/netstack_napi_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..53a0632e4df0bb855ef6171faabd05ca756558c1 --- /dev/null +++ b/utils/napi_utils/include/netstack_napi_utils.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2021-2022 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_NETSTACK_NAPI_UTILS_H +#define COMMUNICATIONNETSTACK_NETSTACK_NAPI_UTILS_H + +#include "napi/native_api.h" +#include +#include + +#define MAX_STRING_LENGTH 4096 + +namespace OHOS::NetStack::NapiUtils { + +napi_valuetype GetValueType(napi_env env, napi_value value); + +/* named property */ +bool HasNamedProperty(napi_env env, napi_value object, const std::string &propertyName); + +napi_value GetNamedProperty(napi_env env, napi_value object, const std::string &propertyName); + +void SetNamedProperty(napi_env env, napi_value object, const std::string &name, napi_value value); + +std::vector GetPropertyNames(napi_env env, napi_value object); + +/* UINT32 */ +napi_value CreateUint32(napi_env env, uint32_t code); + +uint32_t GetUint32FromValue(napi_env env, napi_value value); + +uint32_t GetUint32Property(napi_env env, napi_value object, const std::string &propertyName); + +void SetUint32Property(napi_env env, napi_value object, const std::string &name, uint32_t value); + +/* INT32 */ +napi_value CreateInt32(napi_env env, int32_t code); + +int32_t GetInt32FromValue(napi_env env, napi_value value); + +int32_t GetInt32Property(napi_env env, napi_value object, const std::string &propertyName); + +void SetInt32Property(napi_env env, napi_value object, const std::string &name, int32_t value); + +/* String UTF8 */ +napi_value CreateStringUtf8(napi_env env, const std::string &str); + +std::string GetStringFromValueUtf8(napi_env env, napi_value value); + +std::string GetStringPropertyUtf8(napi_env env, napi_value object, const std::string &propertyName); + +void SetStringPropertyUtf8(napi_env env, napi_value object, const std::string &name, const std::string &value); + +/* array buffer */ +bool ValueIsArrayBuffer(napi_env env, napi_value value); + +void *GetInfoFromArrayBufferValue(napi_env env, napi_value value, size_t *length); + +napi_value CreateArrayBuffer(napi_env env, size_t length, void **data); + +/* object */ +napi_value CreateObject(napi_env env); + +/* undefined */ +napi_value GetUndefined(napi_env env); + +/* function */ +napi_value CallFunction(napi_env env, napi_value recv, napi_value func, size_t argc, const napi_value *argv); + +napi_value CreateFunction(napi_env env, const std::string &name, napi_callback func, void *arg); + +/* reference */ +napi_ref CreateReference(napi_env env, napi_value callback); + +napi_value GetReference(napi_env env, napi_ref callbackRef); + +void DeleteReference(napi_env env, napi_ref callbackRef); + +/* boolean */ +bool GetBooleanProperty(napi_env env, napi_value object, const std::string &propertyName); + +void SetBooleanProperty(napi_env env, napi_value object, const std::string &name, bool value); + +/* define properties */ +void DefineProperties(napi_env env, + napi_value object, + const std::initializer_list &properties); + +} // namespace OHOS::NetStack::NapiUtils + +#endif /* COMMUNICATIONNETSTACK_NETSTACK_NAPI_UTILS_H */ diff --git a/utils/napi_utils/src/netstack_napi_utils.cpp b/utils/napi_utils/src/netstack_napi_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..be6896ec8d4051fc0809a815b81fd25d55a7d290 --- /dev/null +++ b/utils/napi_utils/src/netstack_napi_utils.cpp @@ -0,0 +1,300 @@ +/* + * Copyright (C) 2021-2022 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 "netstack_napi_utils.h" + +#include +#include + +namespace OHOS::NetStack::NapiUtils { + +napi_valuetype GetValueType(napi_env env, napi_value value) +{ + if (value == nullptr) { + return napi_undefined; + } + + napi_valuetype valueType = napi_undefined; + NAPI_CALL_BASE(env, napi_typeof(env, value, &valueType), napi_undefined); + return valueType; +} + +/* named property */ +bool HasNamedProperty(napi_env env, napi_value object, const std::string &propertyName) +{ + bool hasProperty = false; + NAPI_CALL_BASE(env, napi_has_named_property(env, object, propertyName.c_str(), &hasProperty), false); + return hasProperty; +} + +napi_value GetNamedProperty(napi_env env, napi_value object, const std::string &propertyName) +{ + napi_value value = nullptr; + NAPI_CALL(env, napi_get_named_property(env, object, propertyName.c_str(), &value)); + return value; +} + +void SetNamedProperty(napi_env env, napi_value object, const std::string &name, napi_value value) +{ + (void)napi_set_named_property(env, object, name.c_str(), value); +} + +std::vector GetPropertyNames(napi_env env, napi_value object) +{ + std::vector ret; + napi_value names = nullptr; + NAPI_CALL_BASE(env, napi_get_property_names(env, object, &names), ret); + uint32_t length = 0; + NAPI_CALL_BASE(env, napi_get_array_length(env, names, &length), ret); + for (uint32_t index = 0; index < length; ++index) { + napi_value name = nullptr; + if (napi_get_element(env, names, index, &name) != napi_ok) { + continue; + } + if (GetValueType(env, name) != napi_string) { + continue; + } + ret.emplace_back(GetStringFromValueUtf8(env, name)); + } + return ret; +} + +/* UINT32 */ +napi_value CreateUint32(napi_env env, uint32_t code) +{ + napi_value value = nullptr; + if (napi_create_uint32(env, code, &value) != napi_ok) { + return nullptr; + } + return value; +} + +uint32_t GetUint32FromValue(napi_env env, napi_value value) +{ + uint32_t ret = 0; + NAPI_CALL_BASE(env, napi_get_value_uint32(env, value, &ret), 0); + return ret; +} + +uint32_t GetUint32Property(napi_env env, napi_value object, const std::string &propertyName) +{ + if (!HasNamedProperty(env, object, propertyName)) { + return 0; + } + napi_value value = GetNamedProperty(env, object, propertyName); + return GetUint32FromValue(env, value); +} + +void SetUint32Property(napi_env env, napi_value object, const std::string &name, uint32_t value) +{ + napi_value jsValue = CreateUint32(env, value); + if (GetValueType(env, jsValue) != napi_number) { + return; + } + + napi_set_named_property(env, object, name.c_str(), jsValue); +} + +/* INT32 */ +napi_value CreateInt32(napi_env env, int32_t code) +{ + napi_value value = nullptr; + if (napi_create_int32(env, code, &value) != napi_ok) { + return nullptr; + } + return value; +} + +int32_t GetInt32FromValue(napi_env env, napi_value value) +{ + int32_t ret = 0; + NAPI_CALL_BASE(env, napi_get_value_int32(env, value, &ret), 0); + return ret; +} + +int32_t GetInt32Property(napi_env env, napi_value object, const std::string &propertyName) +{ + if (!HasNamedProperty(env, object, propertyName)) { + return 0; + } + napi_value value = GetNamedProperty(env, object, propertyName); + return GetInt32FromValue(env, value); +} + +void SetInt32Property(napi_env env, napi_value object, const std::string &name, int32_t value) +{ + napi_value jsValue = CreateInt32(env, value); + if (GetValueType(env, jsValue) != napi_number) { + return; + } + + napi_set_named_property(env, object, name.c_str(), jsValue); +} + +/* String UTF8 */ +napi_value CreateStringUtf8(napi_env env, const std::string &str) +{ + napi_value value = nullptr; + if (napi_create_string_utf8(env, str.c_str(), strlen(str.c_str()), &value) != napi_ok) { + return nullptr; + } + return value; +} + +std::string GetStringFromValueUtf8(napi_env env, napi_value value) +{ + std::string result; + char str[MAX_STRING_LENGTH] = {0}; + size_t length = 0; + NAPI_CALL_BASE(env, napi_get_value_string_utf8(env, value, str, MAX_STRING_LENGTH, &length), result); + if (length > 0) { + return result.append(str, length); + } + return result; +} + +std::string GetStringPropertyUtf8(napi_env env, napi_value object, const std::string &propertyName) +{ + if (!HasNamedProperty(env, object, propertyName)) { + return ""; + } + napi_value value = GetNamedProperty(env, object, propertyName); + return GetStringFromValueUtf8(env, value); +} + +void SetStringPropertyUtf8(napi_env env, napi_value object, const std::string &name, const std::string &value) +{ + napi_value jsValue = CreateStringUtf8(env, value); + if (GetValueType(env, jsValue) != napi_string) { + return; + } + napi_set_named_property(env, object, name.c_str(), jsValue); +} + +/* array buffer */ +bool ValueIsArrayBuffer(napi_env env, napi_value value) +{ + bool isArrayBuffer = false; + NAPI_CALL_BASE(env, napi_is_arraybuffer(env, value, &isArrayBuffer), false); + return isArrayBuffer; +} + +void *GetInfoFromArrayBufferValue(napi_env env, napi_value value, size_t *length) +{ + if (length == nullptr) { + return nullptr; + } + + void *data = nullptr; + NAPI_CALL(env, napi_get_arraybuffer_info(env, value, &data, length)); + return data; +} + +napi_value CreateArrayBuffer(napi_env env, size_t length, void **data) +{ + if (length == 0) { + return nullptr; + } + napi_value result = nullptr; + NAPI_CALL(env, napi_create_arraybuffer(env, length, data, &result)); + return result; +} + +/* object */ +napi_value CreateObject(napi_env env) +{ + napi_value object = nullptr; + NAPI_CALL(env, napi_create_object(env, &object)); + return object; +} + +/* undefined */ +napi_value GetUndefined(napi_env env) +{ + napi_value undefined = nullptr; + NAPI_CALL(env, napi_get_undefined(env, &undefined)); + return undefined; +} + +/* function */ +napi_value CallFunction(napi_env env, napi_value recv, napi_value func, size_t argc, const napi_value *argv) +{ + napi_value res = nullptr; + NAPI_CALL(env, napi_call_function(env, recv, func, argc, argv, &res)); + return res; +} + +napi_value CreateFunction(napi_env env, const std::string &name, napi_callback func, void *arg) +{ + napi_value res = nullptr; + NAPI_CALL(env, napi_create_function(env, name.c_str(), strlen(name.c_str()), func, arg, &res)); + return res; +} + +/* reference */ +napi_ref CreateReference(napi_env env, napi_value callback) +{ + napi_ref callbackRef = nullptr; + NAPI_CALL(env, napi_create_reference(env, callback, 1, &callbackRef)); + return callbackRef; +} + +napi_value GetReference(napi_env env, napi_ref callbackRef) +{ + napi_value callback = nullptr; + NAPI_CALL(env, napi_get_reference_value(env, callbackRef, &callback)); + return callback; +} + +void DeleteReference(napi_env env, napi_ref callbackRef) +{ + (void)napi_delete_reference(env, callbackRef); +} + +/* boolean */ +bool GetBooleanProperty(napi_env env, napi_value object, const std::string &propertyName) +{ + if (!HasNamedProperty(env, object, propertyName)) { + return false; + } + napi_value value = GetNamedProperty(env, object, propertyName); + bool ret = false; + NAPI_CALL_BASE(env, napi_get_value_bool(env, value, &ret), false); + return ret; +} + +void SetBooleanProperty(napi_env env, napi_value object, const std::string &name, bool value) +{ + napi_value jsValue = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_get_boolean(env, value, &jsValue)); + if (GetValueType(env, jsValue) != napi_boolean) { + return; + } + + napi_set_named_property(env, object, name.c_str(), jsValue); +} + +/* define properties */ +void DefineProperties(napi_env env, + napi_value object, + const std::initializer_list &properties) +{ + napi_property_descriptor descriptors[properties.size()]; + std::copy(properties.begin(), properties.end(), descriptors); + + (void)napi_define_properties(env, object, properties.size(), descriptors); +} + +} // namespace OHOS::NetStack::NapiUtils \ No newline at end of file