1 /*
2 * Copyright (C) 2021 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 #include "host_unity.h"
16
17 namespace Hdc {
HdcHostUnity(HTaskInfo hTaskInfo)18 HdcHostUnity::HdcHostUnity(HTaskInfo hTaskInfo)
19 : HdcTaskBase(hTaskInfo)
20 {
21 opContext.thisClass = this;
22 }
23
~HdcHostUnity()24 HdcHostUnity::~HdcHostUnity()
25 {
26 WRITE_LOG(LOG_DEBUG, "~HdcHostUnity channelId:%u", taskInfo->channelId);
27 }
28
ReadyForRelease()29 bool HdcHostUnity::ReadyForRelease()
30 {
31 if (!HdcTaskBase::ReadyForRelease()) {
32 WRITE_LOG(LOG_WARN, "not ready for release channelId:%u", taskInfo->channelId);
33 return false;
34 }
35 if (opContext.enableLog && !opContext.hasFilelogClosed) {
36 WRITE_LOG(LOG_WARN, "enableLog true hasFilelogClosed false channelId:%u", taskInfo->channelId);
37 return false;
38 }
39 return true;
40 }
41
StopTask()42 void HdcHostUnity::StopTask()
43 {
44 // Do not detect RunningProtect, force to close
45 if (opContext.hasFilelogClosed) {
46 WRITE_LOG(LOG_WARN, "StopTask hasFilelogClosed true channelId:%u", taskInfo->channelId);
47 return;
48 }
49 if (opContext.enableLog) {
50 ++refCount;
51 opContext.fsClose.data = &opContext;
52 WRITE_LOG(LOG_DEBUG, "taskInfo->channelId:%u fileLog:%d", taskInfo->channelId, opContext.fileLog);
53 uv_fs_close(loopTask, &opContext.fsClose, opContext.fileLog, OnFileClose);
54 }
55 };
56
OnFileClose(uv_fs_t * req)57 void HdcHostUnity::OnFileClose(uv_fs_t *req)
58 {
59 uv_fs_req_cleanup(req);
60 ContextUnity *context = reinterpret_cast<ContextUnity *>(req->data);
61 HdcHostUnity *thisClass = reinterpret_cast<HdcHostUnity *>(context->thisClass);
62 context->hasFilelogClosed = true;
63 --thisClass->refCount;
64 return;
65 }
66
InitLocalLog(const char * path)67 bool HdcHostUnity::InitLocalLog(const char *path)
68 {
69 uv_fs_t reqFs;
70 // block open
71 if (uv_fs_open(nullptr, &reqFs, path, UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY, S_IWUSR | S_IRUSR, nullptr)
72 < 0) {
73 WRITE_LOG(LOG_FATAL, "InitLocalLog uv_fs_open failed taskInfo->channelId:%u", taskInfo->channelId);
74 return false;
75 }
76 uv_fs_req_cleanup(&reqFs);
77 opContext.fileLog = reqFs.result;
78 return true;
79 }
80
OnFileIO(uv_fs_t * req)81 void HdcHostUnity::OnFileIO(uv_fs_t *req)
82 {
83 CtxUnityIO *contextIO = reinterpret_cast<CtxUnityIO *>(req->data);
84 ContextUnity *context = reinterpret_cast<ContextUnity *>(contextIO->context);
85 HdcHostUnity *thisClass = reinterpret_cast<HdcHostUnity *>(context->thisClass);
86 CALLSTAT_GUARD(*(thisClass->loopTaskStatus), req->loop, "HdcHostUnity::OnFileIO");
87 uint8_t *bufIO = contextIO->bufIO;
88 uv_fs_req_cleanup(req);
89 --thisClass->refCount;
90 while (true) {
91 if (req->result <= 0) {
92 if (req->result < 0) {
93 constexpr int bufSize = 1024;
94 char buf[bufSize] = { 0 };
95 uv_strerror_r((int)req->result, buf, bufSize);
96 WRITE_LOG(LOG_DEBUG, "Error OnFileIO: %s", buf);
97 }
98 break;
99 }
100 context->fileIOIndex += req->result;
101 break;
102 }
103 delete[] bufIO;
104 delete contextIO; // req is part of contextIO, no need to release
105 }
106
AppendLocalLog(const char * bufLog,const int sizeLog)107 bool HdcHostUnity::AppendLocalLog(const char *bufLog, const int sizeLog)
108 {
109 auto buf = new uint8_t[sizeLog];
110 auto contextIO = new CtxUnityIO();
111 if (!buf || !contextIO) {
112 if (buf) {
113 delete[] buf;
114 }
115 if (contextIO) {
116 delete contextIO;
117 }
118 return false;
119 }
120 if (memcpy_s(buf, sizeLog, bufLog, sizeLog) != EOK) {
121 delete contextIO;
122 delete[] buf;
123 return false;
124 }
125 uv_fs_t *req = &contextIO->fs;
126 contextIO->bufIO = buf;
127 contextIO->context = &opContext;
128 req->data = contextIO;
129 ++refCount;
130
131 uv_buf_t iov = uv_buf_init(reinterpret_cast<char *>(buf), sizeLog);
132 uv_fs_write(loopTask, req, opContext.fileLog, &iov, 1, opContext.fileBufIndex, OnFileIO);
133 opContext.fileBufIndex += sizeLog;
134 return true;
135 }
136
CommandDispatch(const uint16_t command,uint8_t * payload,const int payloadSize)137 bool HdcHostUnity::CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize)
138 {
139 bool ret = true;
140 // Both are executed, do not need to detect ChildReady
141 switch (command) {
142 case CMD_UNITY_BUGREPORT_INIT: {
143 if (strlen(reinterpret_cast<char *>(payload))) { // enable local log
144 if (!InitLocalLog(reinterpret_cast<const char *>(payload))) {
145 LogMsg(MSG_FAIL, "Cannot set locallog");
146 ret = false;
147 break;
148 };
149 opContext.enableLog = true;
150 }
151 SendToAnother(CMD_UNITY_BUGREPORT_INIT, nullptr, 0);
152 break;
153 }
154 case CMD_UNITY_BUGREPORT_DATA: {
155 if (opContext.enableLog) {
156 AppendLocalLog(reinterpret_cast<const char *>(payload), payloadSize);
157 } else {
158 ServerCommand(CMD_KERNEL_ECHO_RAW, payload, payloadSize);
159 }
160 break;
161 }
162 default:
163 break;
164 }
165 return ret;
166 };
167 } // namespace Hdc
168