Line data Source code
1 : /**
2 : * Copyright (c) 2025 Huawei Technologies Co., Ltd.
3 : * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4 : * CANN Open Software License Agreement Version 2.0 (the "License").
5 : * Please refer to the License for details. You may not use this file except in compliance with the License.
6 : * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7 : * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8 : * See LICENSE in the root of the software repository for the full text of the License.
9 : */
10 :
11 : #include "adx_dump_receive.h"
12 : #include <algorithm>
13 : #include "mmpa_api.h"
14 : #include "memory_utils.h"
15 : #include "adx_dump_record.h"
16 : #include "log/adx_log.h"
17 : namespace Adx {
18 6 : int32_t AdxDumpReceive::Init()
19 : {
20 6 : init_ = true;
21 6 : return IDE_DAEMON_OK;
22 : }
23 :
24 14 : int32_t AdxDumpReceive::Process(const CommHandle& handle, const SharedPtr<MsgProto>& proto)
25 : {
26 : // hand shake control(sent by IdeDumpStart)
27 14 : if (proto->msgType == MsgType::MSG_CTRL && proto->status == MsgStatus::MSG_STATUS_HAND_SHAKE) {
28 36 : IdeErrorT err = AdxMsgProto::SendResponse(
29 12 : handle, (CmdClassT)proto->reqType, proto->devId, MsgStatus::MSG_STATUS_NONE_ERROR);
30 12 : if (err != IDE_DAEMON_NONE_ERROR) {
31 1 : IDE_LOGE(
32 : "send dump handshake response failed! device(id:%u,session:%zu), err: %d", proto->devId, handle.session,
33 : err);
34 1 : return err;
35 : }
36 : } else {
37 2 : IDE_LOGW(
38 : "receive invalid ctrl msg! device(id:%u,session:%zu), type: %d, status: %d", proto->devId, handle.session,
39 : proto->msgType, proto->status);
40 2 : return IDE_DAEMON_OK;
41 : }
42 : // store client session(persistent session. must be closed before close server)
43 11 : AdxCommHandle adxHandle = const_cast<AdxCommHandle>(&handle);
44 11 : StoreSession(proto->devId, adxHandle);
45 : // read dump data(sent by IdeDumpData) and end dump control(sent by IdeDumpEnd)
46 11 : int32_t ret = Receive(handle, proto);
47 11 : ReleaseSession(proto->devId, adxHandle);
48 11 : return ret;
49 : }
50 :
51 11 : int32_t AdxDumpReceive::Receive(const CommHandle& handle, const SharedPtr<MsgProto>& proto)
52 : {
53 11 : int32_t length = 0;
54 11 : uint32_t protoHeaderLen = static_cast<uint32_t>(sizeof(MsgProto));
55 11 : uint32_t chunkHeaderLen = static_cast<uint32_t>(sizeof(DumpChunk));
56 11 : MsgProto* msg = nullptr;
57 14 : while (init_) {
58 13 : IDE_LOGI("receiving new dump data from device(id:%u,session:%zu)", proto->devId, handle.session);
59 13 : int ret = AdxCommOptManager::Instance().Read(handle, (IdeRecvBuffT)&msg, length, COMM_OPT_BLOCK);
60 22 : IDE_CTRL_VALUE_WARN(
61 : ret == IDE_DAEMON_OK, return ret, "read dump data error. device(id:%u,session:%zu), err:%d", proto->devId,
62 : handle.session, ret);
63 12 : IDE_CTRL_VALUE_WARN(
64 : msg != nullptr && length >= 0,
65 : {
66 : IdeXfree(msg);
67 : return IDE_DAEMON_ERROR;
68 : },
69 : "dump data is invalid. device(id:%u,session:%zu)", proto->devId, handle.session);
70 :
71 11 : uint32_t protoEntryLen = static_cast<uint32_t>(length);
72 11 : IDE_CTRL_VALUE_WARN(
73 : protoEntryLen >= protoHeaderLen,
74 : {
75 : IdeXfree(msg);
76 : return IDE_DAEMON_ERROR;
77 : },
78 : "recvLen(%u) too small for MsgProto header(%u bytes)", protoEntryLen, protoHeaderLen);
79 :
80 10 : SharedPtr<MsgProto> msgPtr(msg, IdeXfree);
81 10 : msg = nullptr;
82 10 : if (msgPtr->msgType == MsgType::MSG_CTRL) {
83 4 : if (msgPtr->status == MsgStatus::MSG_STATUS_DATA_END) {
84 3 : IDE_LOGI(
85 : "received dump ctrl msg from device(id:%u,session:%zu), end transfer dump data", proto->devId,
86 : handle.session);
87 3 : return IDE_DAEMON_OK;
88 : } else {
89 1 : continue;
90 : }
91 : }
92 6 : uint32_t protoDataLen = protoEntryLen - protoHeaderLen;
93 6 : IDE_CTRL_VALUE_WARN(
94 : msgPtr->sliceLen == protoDataLen, return IDE_DAEMON_ERROR,
95 : "msg sliceLen(%u) not equal actual msg data buffer size(%u)", msgPtr->sliceLen, protoDataLen);
96 :
97 5 : IDE_CTRL_VALUE_WARN(
98 : protoDataLen >= chunkHeaderLen, return IDE_DAEMON_ERROR,
99 : "msg dataLen(%u) too small for DumpChunk header(%u)", protoDataLen, chunkHeaderLen);
100 :
101 4 : DumpChunk* dumpChunk = reinterpret_cast<DumpChunk*>(msgPtr->data);
102 4 : uint32_t chunkDataLen = protoDataLen - chunkHeaderLen;
103 4 : IDE_CTRL_VALUE_WARN(
104 : dumpChunk->bufLen <= chunkDataLen, return IDE_DAEMON_ERROR,
105 : "chunk bufLen(%u) exceeds actual chunk data buffer size(%u)", dumpChunk->bufLen, chunkDataLen);
106 :
107 3 : IDE_LOGI(
108 : "fileName: %s, bufLen: %u, isLastChunk: %u, offset: %ld, flag: %d", dumpChunk->fileName, dumpChunk->bufLen,
109 : dumpChunk->isLastChunk, dumpChunk->offset, dumpChunk->flag);
110 :
111 3 : HostDumpDataInfo data = {msgPtr, protoDataLen};
112 3 : MsgStatus status = MsgStatus::MSG_STATUS_NONE_ERROR;
113 3 : if (!AdxDumpRecord::Instance().RecordDumpDataToQueue(data)) {
114 1 : status = MsgStatus::MSG_STATUS_CACHE_FULL_ERROR;
115 : }
116 :
117 : // send respone msg to device
118 3 : IdeErrorT err = AdxMsgProto::SendResponse(handle, proto->reqType, proto->devId, status);
119 3 : IDE_CTRL_VALUE_FAILED(
120 : err == IDE_DAEMON_NONE_ERROR, return IDE_DAEMON_ERROR,
121 : "send dump handshake response failed! device(id:%u,session:%zu), err: %d", proto->devId, handle.session,
122 : err);
123 11 : }
124 1 : return IDE_DAEMON_OK;
125 : }
126 :
127 7 : int32_t AdxDumpReceive::UnInit()
128 : {
129 7 : init_ = false;
130 7 : return IDE_DAEMON_OK;
131 : }
132 :
133 12 : void AdxDumpReceive::StoreSession(uint32_t deviceId, AdxCommHandle handle)
134 : {
135 12 : if (handle != nullptr) {
136 12 : std::lock_guard<std::mutex> lock{mutex_};
137 12 : handles_[deviceId].push_back(handle);
138 12 : }
139 12 : }
140 :
141 11 : void AdxDumpReceive::ReleaseSession(uint32_t deviceId, AdxCommHandle handle)
142 : {
143 11 : if (handle != nullptr) {
144 11 : std::lock_guard<std::mutex> lock{mutex_};
145 11 : auto map_it = handles_.find(deviceId);
146 11 : if (map_it != handles_.end()) {
147 11 : auto& vec = map_it->second;
148 11 : auto vec_it = std::find(vec.begin(), vec.end(), handle);
149 22 : if (vec_it != vec.end()) {
150 11 : vec.erase(vec_it);
151 : }
152 : }
153 11 : }
154 11 : }
155 :
156 4 : int32_t AdxDumpReceive::Terminate()
157 : {
158 4 : std::lock_guard<std::mutex> lock{mutex_};
159 5 : for (auto& map_it : handles_) {
160 3 : for (auto& handle : map_it.second) {
161 1 : IDE_LOGW("close alive client session. device: %u, session: %zu", map_it.first, handle->session);
162 1 : (void)AdxCommOptManager::Instance().Close(*handle);
163 : }
164 : }
165 4 : handles_.clear();
166 4 : return IDE_DAEMON_OK;
167 4 : }
168 : } // namespace Adx
|