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,const std::shared_ptr<EventManager> & manager)26 SendContext::SendContext(napi_env env, const std::shared_ptr<EventManager> &manager)
27 : BaseContext(env, manager), data(nullptr), length(0), protocol(LWS_WRITE_TEXT)
28 {
29 }
30
HandleParseString(napi_value * params)31 bool SendContext::HandleParseString(napi_value *params)
32 {
33 NETSTACK_LOGI("SendContext data is String");
34 std::string str = NapiUtils::GetStringFromValueUtf8(GetEnv(), params[0]);
35 // must have PRE and POST
36 size_t dataLen = LWS_SEND_BUFFER_PRE_PADDING + str.length() + LWS_SEND_BUFFER_POST_PADDING;
37 if (dataLen == 0 || dataLen > MAX_LIMIT) {
38 NETSTACK_LOGE("SendContext data is exceeded the limit");
39 return false;
40 }
41 data = malloc(dataLen);
42 if (data == nullptr) {
43 NETSTACK_LOGE("no memory");
44 return false;
45 }
46 if (memcpy_s(reinterpret_cast<void *>(reinterpret_cast<uint8_t *>(data) + LWS_SEND_BUFFER_PRE_PADDING),
47 str.length(), str.c_str(), str.length()) < 0) {
48 NETSTACK_LOGE("copy failed");
49 free(data);
50 return false;
51 }
52 length = str.length();
53 protocol = LWS_WRITE_TEXT;
54 return true;
55 }
56
HandleParseArrayBuffer(napi_value * params)57 bool SendContext::HandleParseArrayBuffer(napi_value *params)
58 {
59 NETSTACK_LOGD("SendContext data is ArrayBuffer");
60 size_t len = 0;
61 void *mem = NapiUtils::GetInfoFromArrayBufferValue(GetEnv(), params[0], &len);
62 if (mem == nullptr || len == 0) {
63 NETSTACK_LOGE("no memory");
64 return false;
65 }
66 // must have PRE and POST
67 size_t dataLen = LWS_SEND_BUFFER_PRE_PADDING + len + LWS_SEND_BUFFER_POST_PADDING;
68 if (dataLen == 0 || dataLen > MAX_LIMIT) {
69 NETSTACK_LOGE("SendContext data is exceeded the limit");
70 return false;
71 }
72 data = malloc(dataLen);
73 if (data == nullptr) {
74 NETSTACK_LOGE("no memory");
75 return false;
76 }
77 if (memcpy_s(reinterpret_cast<void *>(reinterpret_cast<uint8_t *>(data) + LWS_SEND_BUFFER_PRE_PADDING), len, mem,
78 len) < 0) {
79 NETSTACK_LOGE("copy failed");
80 free(data);
81 return false;
82 }
83 length = len;
84 protocol = LWS_WRITE_BINARY;
85 return true;
86 }
87
ParseParams(napi_value * params,size_t paramsCount)88 void SendContext::ParseParams(napi_value *params, size_t paramsCount)
89 {
90 if (!CheckParamsType(params, paramsCount)) {
91 NETSTACK_LOGE("SendContext Parse Failed");
92 if (paramsCount == FUNCTION_PARAM_ONE) {
93 if (NapiUtils::GetValueType(GetEnv(), params[0]) == napi_function) {
94 SetCallback(params[0]);
95 }
96 return;
97 }
98
99 if (paramsCount == FUNCTION_PARAM_TWO) {
100 if (NapiUtils::GetValueType(GetEnv(), params[1]) == napi_function) {
101 SetCallback(params[1]);
102 }
103 return;
104 }
105 return;
106 }
107
108 if (NapiUtils::GetValueType(GetEnv(), params[0]) == napi_string) {
109 if (!HandleParseString(params)) {
110 return;
111 }
112 } else {
113 if (!HandleParseArrayBuffer(params)) {
114 return;
115 }
116 }
117
118 if (NapiUtils::GetValueType(GetEnv(), params[1]) == napi_function) {
119 return SetParseOK(SetCallback(params[1]) == napi_ok);
120 }
121
122 NETSTACK_LOGD("SendContext SetParseOK");
123 return SetParseOK(true);
124 }
125
CheckParamsType(napi_value * params,size_t paramsCount)126 bool SendContext::CheckParamsType(napi_value *params, size_t paramsCount)
127 {
128 if (paramsCount == FUNCTION_PARAM_ONE) {
129 return NapiUtils::GetValueType(GetEnv(), params[0]) == napi_string ||
130 NapiUtils::ValueIsArrayBuffer(GetEnv(), params[0]);
131 }
132
133 if (paramsCount == FUNCTION_PARAM_TWO) {
134 return (NapiUtils::GetValueType(GetEnv(), params[0]) == napi_string ||
135 NapiUtils::ValueIsArrayBuffer(GetEnv(), params[0])) &&
136 NapiUtils::GetValueType(GetEnv(), params[1]) == napi_function;
137 }
138
139 return false;
140 }
141
GetErrorCode() const142 int32_t SendContext::GetErrorCode() const
143 {
144 if (BaseContext::IsPermissionDenied()) {
145 return PERMISSION_DENIED_CODE;
146 }
147
148 auto err = BaseContext::GetErrorCode();
149 if (err == PARSE_ERROR_CODE) {
150 return PARSE_ERROR_CODE;
151 }
152 if (WEBSOCKET_ERR_MAP.find(err) != WEBSOCKET_ERR_MAP.end()) {
153 return err;
154 }
155 return WEBSOCKET_CONNECT_FAILED;
156 }
157
GetErrorMessage() const158 std::string SendContext::GetErrorMessage() const
159 {
160 if (BaseContext::IsPermissionDenied()) {
161 return PERMISSION_DENIED_MSG;
162 }
163
164 auto err = BaseContext::GetErrorCode();
165 if (err == PARSE_ERROR_CODE) {
166 return PARSE_ERROR_MSG;
167 }
168 auto it = WEBSOCKET_ERR_MAP.find(err);
169 if (it != WEBSOCKET_ERR_MAP.end()) {
170 return it->second;
171 }
172 it = WEBSOCKET_ERR_MAP.find(WEBSOCKET_UNKNOWN_OTHER_ERROR);
173 if (it != WEBSOCKET_ERR_MAP.end()) {
174 return it->second;
175 }
176 return {};
177 }
178 } // namespace OHOS::NetStack::Websocket
179