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> &notifyData, 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