1 /*
2 * Copyright (c) 2024 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 "response_message_receiver.h"
17
18 #include <unistd.h>
19
20 #include <cstdint>
21 #include <cstdlib>
22 #include <sstream>
23 #include <string>
24 #include <vector>
25
26 #include "log.h"
27
28 namespace OHOS::Request {
29
30 static constexpr int32_t INT64_SIZE = 8;
31 static constexpr int32_t INT32_SIZE = 4;
32 static constexpr int32_t INT16_SIZE = 2;
33 // static constexpr int32_t INT8_SIZE = 1;
34
35 std::shared_ptr<OHOS::AppExecFwk::EventHandler> serviceHandler_;
36
Int64FromParcel(int64_t & num,char * & parcel,int32_t & size)37 int32_t ResponseMessageReceiver::Int64FromParcel(int64_t &num, char *&parcel, int32_t &size)
38 {
39 if (size < INT64_SIZE) {
40 REQUEST_HILOGE("message not complete");
41 return -1;
42 }
43 num = *reinterpret_cast<int64_t *>(parcel);
44 parcel += INT64_SIZE;
45 size -= INT64_SIZE;
46 return 0;
47 }
48
Uint64FromParcel(uint64_t & num,char * & parcel,int32_t & size)49 int32_t ResponseMessageReceiver::Uint64FromParcel(uint64_t &num, char *&parcel, int32_t &size)
50 {
51 if (size < INT64_SIZE) {
52 REQUEST_HILOGE("message not complete");
53 return -1;
54 }
55 num = *reinterpret_cast<uint64_t *>(parcel);
56 parcel += INT64_SIZE;
57 size -= INT64_SIZE;
58 return 0;
59 }
60
Int32FromParcel(int32_t & num,char * & parcel,int32_t & size)61 int32_t ResponseMessageReceiver::Int32FromParcel(int32_t &num, char *&parcel, int32_t &size)
62 {
63 if (size < INT32_SIZE) {
64 REQUEST_HILOGE("message not complete");
65 return -1;
66 }
67 num = *reinterpret_cast<int32_t *>(parcel);
68 parcel += INT32_SIZE;
69 size -= INT32_SIZE;
70 return 0;
71 }
72
Uint32FromParcel(uint32_t & num,char * & parcel,int32_t & size)73 int32_t ResponseMessageReceiver::Uint32FromParcel(uint32_t &num, char *&parcel, int32_t &size)
74 {
75 if (size < INT32_SIZE) {
76 REQUEST_HILOGE("message not complete");
77 return -1;
78 }
79 num = *reinterpret_cast<uint32_t *>(parcel);
80 parcel += INT32_SIZE;
81 size -= INT32_SIZE;
82 return 0;
83 }
84
Int16FromParcel(int16_t & num,char * & parcel,int32_t & size)85 int32_t ResponseMessageReceiver::Int16FromParcel(int16_t &num, char *&parcel, int32_t &size)
86 {
87 if (size < INT16_SIZE) {
88 REQUEST_HILOGE("message not complete");
89 return -1;
90 }
91 num = *reinterpret_cast<int16_t *>(parcel);
92 parcel += INT16_SIZE;
93 size -= INT16_SIZE;
94 return 0;
95 }
96
StateFromParcel(State & state,char * & parcel,int32_t & size)97 int32_t ResponseMessageReceiver::StateFromParcel(State &state, char *&parcel, int32_t &size)
98 {
99 uint32_t temp;
100 if (Uint32FromParcel(temp, parcel, size) || temp > static_cast<uint32_t>(State::ANY)) {
101 return -1;
102 }
103 state = static_cast<State>(temp);
104 return 0;
105 }
106
ActionFromParcel(Action & action,char * & parcel,int32_t & size)107 int32_t ResponseMessageReceiver::ActionFromParcel(Action &action, char *&parcel, int32_t &size)
108 {
109 uint32_t temp;
110 if (Uint32FromParcel(temp, parcel, size) || temp > static_cast<uint32_t>(Action::ANY)) {
111 return -1;
112 }
113 action = static_cast<Action>(temp);
114 return 0;
115 }
116
VersionFromParcel(Version & version,char * & parcel,int32_t & size)117 int32_t ResponseMessageReceiver::VersionFromParcel(Version &version, char *&parcel, int32_t &size)
118 {
119 uint32_t temp;
120 if (Uint32FromParcel(temp, parcel, size) || temp > static_cast<uint32_t>(Version::API10)) {
121 return -1;
122 }
123 version = static_cast<Version>(temp);
124 return 0;
125 }
126
SubscribeTypeFromParcel(SubscribeType & type,char * & parcel,int32_t & size)127 int32_t ResponseMessageReceiver::SubscribeTypeFromParcel(SubscribeType &type, char *&parcel, int32_t &size)
128 {
129 uint32_t temp;
130 if (Uint32FromParcel(temp, parcel, size) || temp > static_cast<uint32_t>(SubscribeType::BUTT)) {
131 return -1;
132 }
133 type = static_cast<SubscribeType>(temp);
134 return 0;
135 }
136
StringFromParcel(std::string & str,char * & parcel,int32_t & size)137 int32_t ResponseMessageReceiver::StringFromParcel(std::string &str, char *&parcel, int32_t &size)
138 {
139 int32_t i = 0;
140
141 while (i < size && parcel[i] != '\0') {
142 ++i;
143 }
144
145 if (i < size) {
146 str.assign(parcel, i);
147 parcel += (i + 1);
148 size -= (i + 1);
149 return 0;
150 } else {
151 REQUEST_HILOGE("message not complete");
152 return -1;
153 }
154 }
155
ResponseHeaderFromParcel(std::map<std::string,std::vector<std::string>> & headers,char * & parcel,int32_t & size)156 int32_t ResponseMessageReceiver::ResponseHeaderFromParcel(
157 std::map<std::string, std::vector<std::string>> &headers, char *&parcel, int32_t &size)
158 {
159 std::string s(parcel, size);
160 std::stringstream ss(s);
161 std::string line;
162 while (std::getline(ss, line, '\n')) {
163 std::stringstream keyValue(line);
164 std::string key;
165 std::string valueLine;
166 std::getline(keyValue, key, ':');
167 std::getline(keyValue, valueLine);
168 std::stringstream values(valueLine);
169 std::string value;
170 while (getline(values, value, ',')) {
171 headers[key].push_back(value);
172 }
173 }
174 return 0;
175 }
176
ProgressExtrasFromParcel(std::map<std::string,std::string> & extras,char * & parcel,int32_t & size)177 int32_t ResponseMessageReceiver::ProgressExtrasFromParcel(
178 std::map<std::string, std::string> &extras, char *&parcel, int32_t &size)
179 {
180 uint32_t length;
181 if (Uint32FromParcel(length, parcel, size)) {
182 return -1;
183 }
184
185 for (uint32_t i = 0; i < length; ++i) {
186 std::string key;
187 std::string value;
188 if (StringFromParcel(key, parcel, size) != 0) {
189 return -1;
190 }
191 if (StringFromParcel(value, parcel, size) != 0) {
192 return -1;
193 }
194 extras[key] = value;
195 }
196
197 return 0;
198 }
199
VecInt64FromParcel(std::vector<int64_t> & vec,char * & parcel,int32_t & size)200 int32_t ResponseMessageReceiver::VecInt64FromParcel(std::vector<int64_t> &vec, char *&parcel, int32_t &size)
201 {
202 uint32_t length;
203 if (Uint32FromParcel(length, parcel, size)) {
204 return -1;
205 }
206 for (uint32_t i = 0; i < length; ++i) {
207 int64_t value;
208 if (Int64FromParcel(value, parcel, size)) {
209 return -1;
210 }
211 vec.push_back(value);
212 }
213
214 return 0;
215 }
216
ResponseMessageReceiver(IResponseMessageHandler * handler,int32_t sockFd)217 ResponseMessageReceiver::ResponseMessageReceiver(IResponseMessageHandler *handler, int32_t sockFd)
218 : handler_(handler), sockFd_(sockFd)
219 {
220 }
221
BeginReceive()222 void ResponseMessageReceiver::BeginReceive()
223 {
224 std::shared_ptr<OHOS::AppExecFwk::EventRunner> runner = OHOS::AppExecFwk::EventRunner::GetMainEventRunner();
225 serviceHandler_ = std::make_shared<OHOS::AppExecFwk::EventHandler>(runner);
226 serviceHandler_->AddFileDescriptorListener(
227 sockFd_, OHOS::AppExecFwk::FILE_DESCRIPTOR_INPUT_EVENT, shared_from_this(), "subscribe");
228 }
229
230 // ret 0 if success, ret < 0 if fail
MsgHeaderParcel(int32_t & msgId,int16_t & msgType,int16_t & bodySize,char * & parcel,int32_t & size)231 int32_t ResponseMessageReceiver::MsgHeaderParcel(
232 int32_t &msgId, int16_t &msgType, int16_t &bodySize, char *&parcel, int32_t &size)
233 {
234 int32_t magicNum = 0;
235 if (Int32FromParcel(magicNum, parcel, size) != 0) {
236 return -1;
237 }
238 if (magicNum != ResponseMessageReceiver::RESPONSE_MAGIC_NUM) {
239 REQUEST_HILOGE("Bad magic num, %{public}d", magicNum);
240 return -1;
241 }
242
243 if (Int32FromParcel(msgId, parcel, size) != 0) {
244 return -1;
245 }
246 if (Int16FromParcel(msgType, parcel, size) != 0) {
247 return -1;
248 }
249 if (Int16FromParcel(bodySize, parcel, size) != 0) {
250 return -1;
251 }
252 return 0;
253 }
254
ResponseFromParcel(std::shared_ptr<Response> & response,char * & parcel,int32_t & size)255 int32_t ResponseMessageReceiver::ResponseFromParcel(std::shared_ptr<Response> &response, char *&parcel, int32_t &size)
256 {
257 int32_t tid;
258 if (Int32FromParcel(tid, parcel, size) != 0) {
259 REQUEST_HILOGE("Bad tid");
260 return -1;
261 }
262 response->taskId = std::to_string(tid);
263
264 if (StringFromParcel(response->version, parcel, size) != 0) {
265 REQUEST_HILOGE("Bad version");
266 return -1;
267 }
268
269 if (Int32FromParcel(response->statusCode, parcel, size) != 0) {
270 REQUEST_HILOGE("Bad statusCode");
271 return -1;
272 }
273
274 if (StringFromParcel(response->reason, parcel, size) != 0) {
275 REQUEST_HILOGE("Bad reason");
276 return -1;
277 }
278
279 ResponseHeaderFromParcel(response->headers, parcel, size);
280 return 0;
281 }
282
TaskStatesFromParcel(std::vector<TaskState> & taskStates,char * & parcel,int32_t & size)283 int32_t ResponseMessageReceiver::TaskStatesFromParcel(std::vector<TaskState> &taskStates, char *&parcel, int32_t &size)
284 {
285 uint32_t length;
286 if (Uint32FromParcel(length, parcel, size) != 0) {
287 REQUEST_HILOGE("Bad type");
288 return -1;
289 }
290 for (uint32_t i = 0; i < length; ++i) {
291 TaskState taskState;
292 if (StringFromParcel(taskState.path, parcel, size) != 0) {
293 REQUEST_HILOGE("Bad path");
294 return -1;
295 }
296 if (Uint32FromParcel(taskState.responseCode, parcel, size) != 0) {
297 REQUEST_HILOGE("Bad responseCode");
298 return -1;
299 }
300 if (StringFromParcel(taskState.message, parcel, size) != 0) {
301 REQUEST_HILOGE("Bad message");
302 return -1;
303 }
304 taskStates.push_back(taskState);
305 }
306 return 0;
307 }
308
NotifyDataFromParcel(std::shared_ptr<NotifyData> & notifyData,char * & parcel,int32_t & size)309 int32_t ResponseMessageReceiver::NotifyDataFromParcel(
310 std::shared_ptr<NotifyData> ¬ifyData, char *&parcel, int32_t &size)
311 {
312 if (SubscribeTypeFromParcel(notifyData->type, parcel, size) != 0) {
313 REQUEST_HILOGE("Bad type");
314 return -1;
315 }
316 if (Uint32FromParcel(notifyData->taskId, parcel, size) != 0) {
317 REQUEST_HILOGE("Bad tid");
318 return -1;
319 }
320 if (StateFromParcel(notifyData->progress.state, parcel, size) != 0) {
321 REQUEST_HILOGE("Bad state");
322 return -1;
323 }
324 if (Uint32FromParcel(notifyData->progress.index, parcel, size) != 0) {
325 REQUEST_HILOGE("Bad index");
326 return -1;
327 }
328 if (Uint64FromParcel(notifyData->progress.processed, parcel, size) != 0) {
329 REQUEST_HILOGE("Bad processed");
330 return -1;
331 }
332 if (Uint64FromParcel(notifyData->progress.totalProcessed, parcel, size) != 0) {
333 REQUEST_HILOGE("Bad totalProcessed");
334 return -1;
335 }
336 if (VecInt64FromParcel(notifyData->progress.sizes, parcel, size) != 0) {
337 REQUEST_HILOGE("Bad sizes");
338 return -1;
339 }
340 if (ProgressExtrasFromParcel(notifyData->progress.extras, parcel, size) != 0) {
341 REQUEST_HILOGE("Bad extras");
342 return -1;
343 }
344
345 if (ActionFromParcel(notifyData->action, parcel, size) != 0) {
346 REQUEST_HILOGE("Bad action");
347 return -1;
348 }
349 if (VersionFromParcel(notifyData->version, parcel, size) != 0) {
350 REQUEST_HILOGE("Bad version");
351 return -1;
352 }
353 if (TaskStatesFromParcel(notifyData->taskStates, parcel, size) != 0) {
354 REQUEST_HILOGE("Bad taskStates");
355 return -1;
356 }
357 return 0;
358 }
359
OnReadable(int32_t fd)360 void ResponseMessageReceiver::OnReadable(int32_t fd)
361 {
362 int readSize = ResponseMessageReceiver::RESPONSE_MAX_SIZE;
363 char buffer[readSize];
364
365 int32_t length = read(fd, buffer, readSize);
366 if (length <= 0) {
367 REQUEST_HILOGE("read message error: %{public}d, %{public}d", length, errno);
368 return;
369 }
370 REQUEST_HILOGD("read message: %{public}d", length);
371
372 char lenBuf[4];
373 *reinterpret_cast<uint32_t *>(lenBuf) = length;
374 int32_t ret = write(fd, lenBuf, 4);
375 if (ret <= 0) {
376 REQUEST_HILOGE("send length back failed: %{public}d", ret);
377 }
378
379 char *leftBuf = buffer;
380 int32_t leftLen = length;
381 int32_t msgId = -1;
382 int16_t msgType = -1;
383 int16_t headerSize = -1;
384 MsgHeaderParcel(msgId, msgType, headerSize, leftBuf, leftLen);
385 if (msgId != messageId_) {
386 REQUEST_HILOGE("Bad messageId, expect %{public}d = %{public}d", msgId, messageId_);
387 }
388 if (headerSize != static_cast<int16_t>(length)) {
389 REQUEST_HILOGE("Bad headerSize, %{public}d, %{public}d", length, headerSize);
390 }
391 ++messageId_;
392
393 if (msgType == MessageType::HTTP_RESPONSE) {
394 std::shared_ptr<Response> response = std::make_shared<Response>();
395 if (ResponseFromParcel(response, leftBuf, leftLen) == 0) {
396 this->handler_->OnResponseReceive(response);
397 } else {
398 REQUEST_HILOGE("Bad Response");
399 }
400 } else if (msgType == MessageType::NOTIFY_DATA) {
401 std::shared_ptr<NotifyData> notifyData = std::make_shared<NotifyData>();
402 if (NotifyDataFromParcel(notifyData, leftBuf, leftLen) == 0) {
403 this->handler_->OnNotifyDataReceive(notifyData);
404 } else {
405 REQUEST_HILOGE("Bad NotifyData");
406 }
407 }
408 }
409
OnShutdown(int32_t fd)410 void ResponseMessageReceiver::OnShutdown(int32_t fd)
411 {
412 REQUEST_HILOGI("uds OnShutdown, %{public}d", fd);
413 serviceHandler_->RemoveFileDescriptorListener(fd);
414 close(fd);
415 this->handler_->OnChannelBroken();
416 }
417
OnException(int32_t fd)418 void ResponseMessageReceiver::OnException(int32_t fd)
419 {
420 REQUEST_HILOGI("uds OnException, %{public}d", fd);
421 serviceHandler_->RemoveFileDescriptorListener(fd);
422 close(fd);
423 this->handler_->OnChannelBroken();
424 }
425
Shutdown()426 void ResponseMessageReceiver::Shutdown()
427 {
428 REQUEST_HILOGI("uds shutdown, %{public}d", sockFd_);
429 serviceHandler_->RemoveFileDescriptorListener(sockFd_);
430 close(sockFd_);
431 this->handler_->OnChannelBroken();
432 }
433
434 } // namespace OHOS::Request