• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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