• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "server_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 namespace OHOS::NetStack::Websocket {
ServerSendContext(napi_env env,const std::shared_ptr<EventManager> & manager)25 ServerSendContext::ServerSendContext(napi_env env, const std::shared_ptr<EventManager> &manager)
26     : BaseContext(env, manager), data(nullptr), length(0), protocol(LWS_WRITE_TEXT), connection() {}
27 
28 ServerSendContext::~ServerSendContext() = default;
29 
ParseParams(napi_value * params,size_t paramsCount)30 void ServerSendContext::ParseParams(napi_value *params, size_t paramsCount)
31 {
32     if (!CheckParamsType(params, paramsCount)) {
33         NETSTACK_LOGE("SendContext Parse Failed");
34         if (paramsCount == FUNCTION_PARAM_ONE) {
35             if (NapiUtils::GetValueType(GetEnv(), params[0]) == napi_object) {
36                 SetCallback(params[0]);
37             }
38             return;
39         }
40 
41         if (paramsCount == FUNCTION_PARAM_TWO) {
42             if (NapiUtils::GetValueType(GetEnv(), params[1]) == napi_object) {
43                 SetCallback(params[1]);
44             }
45             return;
46         }
47         return;
48     }
49 
50     if (NapiUtils::GetValueType(GetEnv(), params[0]) == napi_string) {
51         if (!HandleParseString(params)) {
52             NETSTACK_LOGI("HandleParseString fail");
53             return;
54         }
55     } else {
56         if (!HandleParseArrayBuffer(params)) {
57             NETSTACK_LOGI("HandleParseArrayBuffer fail");
58             return;
59         }
60     }
61 
62     if (!HandleParseConnection(GetEnv(), params[1])) {
63         return;
64     }
65     NETSTACK_LOGD("SendContext SetParseOK");
66     return SetParseOK(true);
67 }
68 
CheckParamsType(napi_value * params,size_t paramsCount)69 bool ServerSendContext::CheckParamsType(napi_value *params, size_t paramsCount)
70 {
71     if (paramsCount == FUNCTION_PARAM_TWO) {
72         return (NapiUtils::GetValueType(GetEnv(), params[0]) == napi_string ||
73             NapiUtils::ValueIsArrayBuffer(GetEnv(), params[0])) &&
74             IsValidWebsocketConnection(GetEnv(), params[1]);
75     }
76     return false;
77 }
78 
IsValidWebsocketConnection(napi_env env,napi_value params)79 bool ServerSendContext::IsValidWebsocketConnection(napi_env env, napi_value params)
80 {
81     NETSTACK_LOGI("IsValidWebsocketConnection enter");
82     if (NapiUtils::GetValueType(env, params) != napi_object) {
83         return false;
84     }
85     return (NapiUtils::GetValueType(env, NapiUtils::GetNamedProperty(env, params,
86         ContextKey::CLIENT_PORT)) == napi_number) && (NapiUtils::GetValueType(env,
87         NapiUtils::GetNamedProperty(env, params, ContextKey::CLIENT_IP)) == napi_string);
88 }
89 
HandleParseString(napi_value * params)90 bool ServerSendContext::HandleParseString(napi_value *params)
91 {
92     NETSTACK_LOGI("Server SendContext data is String");
93     std::string str = NapiUtils::GetStringFromValueUtf8(GetEnv(), params[0]);
94     // must have PRE and POST
95     size_t dataLen = LWS_SEND_BUFFER_PRE_PADDING + str.length() + LWS_SEND_BUFFER_POST_PADDING;
96     if (dataLen == 0 || dataLen > MAX_LIMIT) {
97         NETSTACK_LOGE("ServerSendContext data is exceeded the limit");
98         return false;
99     }
100     data = malloc(dataLen);
101     if (data == nullptr) {
102         NETSTACK_LOGE("no memory");
103         return false;
104     }
105     if (memcpy_s(reinterpret_cast<void *>(reinterpret_cast<uint8_t *>(data) + LWS_SEND_BUFFER_PRE_PADDING),
106         str.length(), str.c_str(), str.length()) < 0) {
107         NETSTACK_LOGE("copy failed");
108         free(data);
109         return false;
110     }
111     length = str.length();
112     protocol = LWS_WRITE_TEXT;
113     return true;
114 }
115 
HandleParseArrayBuffer(napi_value * params)116 bool ServerSendContext::HandleParseArrayBuffer(napi_value *params)
117 {
118     NETSTACK_LOGI("ServerSendContext data is ArrayBuffer");
119     size_t len = 0;
120     void *mem = NapiUtils::GetInfoFromArrayBufferValue(GetEnv(), params[0], &len);
121     if (mem == nullptr || len == 0) {
122         NETSTACK_LOGE("no memory");
123         return false;
124     }
125     // must have PRE and POST
126     size_t dataLen = LWS_SEND_BUFFER_PRE_PADDING + len + LWS_SEND_BUFFER_POST_PADDING;
127     if (dataLen == 0 || dataLen > MAX_LIMIT) {
128         NETSTACK_LOGE("ServerSendContext data is exceeded the limit");
129         return false;
130     }
131     data = malloc(dataLen);
132     if (data == nullptr) {
133         NETSTACK_LOGE("no memory");
134         return false;
135     }
136     if (memcpy_s(reinterpret_cast<void *>(reinterpret_cast<uint8_t *>(data) + LWS_SEND_BUFFER_PRE_PADDING), len, mem,
137         len) < 0) {
138         NETSTACK_LOGE("copy failed");
139         free(data);
140         return false;
141     }
142     length = len;
143     protocol = LWS_WRITE_BINARY;
144     return true;
145 }
146 
HandleParseConnection(napi_env env,napi_value params)147 bool ServerSendContext::HandleParseConnection(napi_env env, napi_value params)
148 {
149     NETSTACK_LOGI("parse websocketconnection enter");
150     if (NapiUtils::GetValueType(env, params) == napi_object) {
151         uint32_t port = NapiUtils::GetUint32Property(env, params, ContextKey::CLIENT_PORT);
152         if (port == 0) {
153             NETSTACK_LOGE("parse clientPort error");
154         }
155         std::string ip = NapiUtils::GetStringPropertyUtf8(env, params, ContextKey::CLIENT_IP);
156         if (ip == "") {
157             NETSTACK_LOGE("parse clientIP error");
158         }
159         SetClientWebSocketConn(port, ip);
160         return true;
161     }
162     return false;
163 }
164 
SetClientWebSocketConn(uint32_t & port,std::string & ip)165 void ServerSendContext::SetClientWebSocketConn(uint32_t &port, std::string &ip)
166 {
167     connection.clientPort = port;
168     connection.clientIP = ip;
169 }
170 
GetConnection() const171 WebSocketConnection ServerSendContext::GetConnection() const
172 {
173     return connection;
174 }
175 
GetErrorCode() const176 int32_t ServerSendContext::GetErrorCode() const
177 {
178     if (BaseContext::IsPermissionDenied()) {
179         return PERMISSION_DENIED_CODE;
180     }
181 
182     auto err = BaseContext::GetErrorCode();
183     if (err == PARSE_ERROR_CODE) {
184         return PARSE_ERROR_CODE;
185     }
186     if (WEBSOCKET_ERR_MAP.find(err) != WEBSOCKET_ERR_MAP.end()) {
187         return err;
188     }
189     return WEBSOCKET_CONNECT_FAILED;
190 }
191 
GetErrorMessage() const192 std::string ServerSendContext::GetErrorMessage() const
193 {
194     if (BaseContext::IsPermissionDenied()) {
195         return PERMISSION_DENIED_MSG;
196     }
197 
198     auto err = BaseContext::GetErrorCode();
199     if (err == PARSE_ERROR_CODE) {
200         return PARSE_ERROR_MSG;
201     }
202     auto it = WEBSOCKET_ERR_MAP.find(err);
203     if (it != WEBSOCKET_ERR_MAP.end()) {
204         return it->second;
205     }
206     it = WEBSOCKET_ERR_MAP.find(WEBSOCKET_UNKNOWN_OTHER_ERROR);
207     if (it != WEBSOCKET_ERR_MAP.end()) {
208         return it->second;
209     }
210     return {};
211 }
212 } // namespace OHOS::NetStack::Websocket