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