1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "send_context.h"
17
18 #include "constant.h"
19 #include "netstack_log.h"
20 #include "napi_utils.h"
21 #include "securec.h"
22
23 static constexpr size_t MAX_LIMIT = 5 * 1024 * 1024;
24
25 namespace OHOS::NetStack::Websocket {
SendContext(napi_env env,EventManager * manager)26 SendContext::SendContext(napi_env env, EventManager *manager)
27 : BaseContext(env, manager), data(nullptr), length(0), protocol(LWS_WRITE_TEXT)
28 {
29 }
30
SendContext(napi_env env,const std::shared_ptr<EventManager> & sharedManager)31 SendContext::SendContext(napi_env env, const std::shared_ptr<EventManager> &sharedManager)
32 : BaseContext(env, sharedManager), data(nullptr), length(0), protocol(LWS_WRITE_TEXT)
33 {
34 }
35
HandleParseString(napi_value * params)36 bool SendContext::HandleParseString(napi_value *params)
37 {
38 NETSTACK_LOGI("SendContext data is String");
39 std::string str = NapiUtils::GetStringFromValueUtf8(GetEnv(), params[0]);
40 // must have PRE and POST
41 size_t dataLen = LWS_SEND_BUFFER_PRE_PADDING + str.length() + LWS_SEND_BUFFER_POST_PADDING;
42 if (dataLen == 0 || dataLen > MAX_LIMIT) {
43 NETSTACK_LOGE("SendContext data is exceeded the limit");
44 return false;
45 }
46 data = malloc(dataLen);
47 if (data == nullptr) {
48 NETSTACK_LOGE("no memory");
49 return false;
50 }
51 if (memcpy_s(reinterpret_cast<void *>(reinterpret_cast<uint8_t *>(data) + LWS_SEND_BUFFER_PRE_PADDING),
52 str.length(), str.c_str(), str.length()) < 0) {
53 NETSTACK_LOGE("copy failed");
54 return false;
55 }
56 length = str.length();
57 protocol = LWS_WRITE_TEXT;
58 return true;
59 }
60
HandleParseArrayBuffer(napi_value * params)61 bool SendContext::HandleParseArrayBuffer(napi_value *params)
62 {
63 NETSTACK_LOGD("SendContext data is ArrayBuffer");
64 size_t len = 0;
65 void *mem = NapiUtils::GetInfoFromArrayBufferValue(GetEnv(), params[0], &len);
66 if (mem == nullptr || len == 0) {
67 NETSTACK_LOGE("no memory");
68 return false;
69 }
70 // must have PRE and POST
71 size_t dataLen = LWS_SEND_BUFFER_PRE_PADDING + len + LWS_SEND_BUFFER_POST_PADDING;
72 if (dataLen == 0 || dataLen > MAX_LIMIT) {
73 NETSTACK_LOGE("SendContext data is exceeded the limit");
74 return false;
75 }
76 data = malloc(dataLen);
77 if (data == nullptr) {
78 NETSTACK_LOGE("no memory");
79 return false;
80 }
81 if (memcpy_s(reinterpret_cast<void *>(reinterpret_cast<uint8_t *>(data) + LWS_SEND_BUFFER_PRE_PADDING), len, mem,
82 len) < 0) {
83 NETSTACK_LOGE("copy failed");
84 return false;
85 }
86 length = len;
87 protocol = LWS_WRITE_BINARY;
88 return true;
89 }
90
ParseParams(napi_value * params,size_t paramsCount)91 void SendContext::ParseParams(napi_value *params, size_t paramsCount)
92 {
93 if (!CheckParamsType(params, paramsCount)) {
94 NETSTACK_LOGE("SendContext Parse Failed");
95 if (paramsCount == FUNCTION_PARAM_ONE) {
96 if (NapiUtils::GetValueType(GetEnv(), params[0]) == napi_function) {
97 SetCallback(params[0]);
98 }
99 return;
100 }
101
102 if (paramsCount == FUNCTION_PARAM_TWO) {
103 if (NapiUtils::GetValueType(GetEnv(), params[1]) == napi_function) {
104 SetCallback(params[1]);
105 }
106 return;
107 }
108 return;
109 }
110
111 if (NapiUtils::GetValueType(GetEnv(), params[0]) == napi_string) {
112 if (!HandleParseString(params)) {
113 return;
114 }
115 } else {
116 if (!HandleParseArrayBuffer(params)) {
117 return;
118 }
119 }
120
121 if (NapiUtils::GetValueType(GetEnv(), params[1]) == napi_function) {
122 return SetParseOK(SetCallback(params[1]) == napi_ok);
123 }
124
125 NETSTACK_LOGD("SendContext SetParseOK");
126 return SetParseOK(true);
127 }
128
CheckParamsType(napi_value * params,size_t paramsCount)129 bool SendContext::CheckParamsType(napi_value *params, size_t paramsCount)
130 {
131 if (paramsCount == FUNCTION_PARAM_ONE) {
132 return NapiUtils::GetValueType(GetEnv(), params[0]) == napi_string ||
133 NapiUtils::ValueIsArrayBuffer(GetEnv(), params[0]);
134 }
135
136 if (paramsCount == FUNCTION_PARAM_TWO) {
137 return (NapiUtils::GetValueType(GetEnv(), params[0]) == napi_string ||
138 NapiUtils::ValueIsArrayBuffer(GetEnv(), params[0])) &&
139 NapiUtils::GetValueType(GetEnv(), params[1]) == napi_function;
140 }
141
142 return false;
143 }
144
GetErrorCode() const145 int32_t SendContext::GetErrorCode() const
146 {
147 if (BaseContext::IsPermissionDenied()) {
148 return PERMISSION_DENIED_CODE;
149 }
150
151 auto err = BaseContext::GetErrorCode();
152 if (err == PARSE_ERROR_CODE) {
153 return PARSE_ERROR_CODE;
154 }
155 if (WEBSOCKET_ERR_MAP.find(err) != WEBSOCKET_ERR_MAP.end()) {
156 return err;
157 }
158 return WEBSOCKET_CONNECT_FAILED;
159 }
160
GetErrorMessage() const161 std::string SendContext::GetErrorMessage() const
162 {
163 if (BaseContext::IsPermissionDenied()) {
164 return PERMISSION_DENIED_MSG;
165 }
166
167 auto err = BaseContext::GetErrorCode();
168 if (err == PARSE_ERROR_CODE) {
169 return PARSE_ERROR_MSG;
170 }
171 auto it = WEBSOCKET_ERR_MAP.find(err);
172 if (it != WEBSOCKET_ERR_MAP.end()) {
173 return it->second;
174 }
175 it = WEBSOCKET_ERR_MAP.find(WEBSOCKET_UNKNOWN_OTHER_ERROR);
176 if (it != WEBSOCKET_ERR_MAP.end()) {
177 return it->second;
178 }
179 return {};
180 }
181 } // namespace OHOS::NetStack::Websocket
182