diff --git a/smartperf_device/device_command/services/ipc/include/sp_server_socket.h b/smartperf_device/device_command/services/ipc/include/sp_server_socket.h new file mode 100644 index 0000000000000000000000000000000000000000..cd680c2ffa24c52431c7288ee4020dec57d3f5a2 --- /dev/null +++ b/smartperf_device/device_command/services/ipc/include/sp_server_socket.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef SP_SERVERSOCKET_H +#define SP_SERVERSOCKET_H +#include +#include +namespace OHOS { +namespace SmartPerf { +enum class ProtoType { + TCP, + UDP, + UDPEX +}; +class SpServerSocket { +public: + SpServerSocket(); + ~SpServerSocket(); + // 创建一个套接字 + int Init(ProtoType type); + // UDP + int Sendto(const std::string &sendBuf); + int Recvfrom(); + // TCP + int Accept(); + int Send(const std::string &sendBuf) const; + int Recv(); + // 关闭 + void Close(); + std::string RecvBuf() const; + +private: + int sock = -1; + struct sockaddr_in local; + struct sockaddr_in client; + int sockPort; + int connFd = -1; + const int listenCount = 5; + const static int buffSizeRecv = 1024; + char rbuf[buffSizeRecv] = ""; + const int udpPort = 8283; + const int tcpPort = 8284; + const int udpExPort = 8285; +}; +} +} + +#endif // !SPSERVERSOCKET \ No newline at end of file diff --git a/smartperf_device/device_command/services/ipc/include/sp_thread_socket.h b/smartperf_device/device_command/services/ipc/include/sp_thread_socket.h new file mode 100644 index 0000000000000000000000000000000000000000..fd296e35361360e92631a13aaaa65306413c453c --- /dev/null +++ b/smartperf_device/device_command/services/ipc/include/sp_thread_socket.h @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef SP_THREAD_SOCKET_H +#define SP_THREAD_SOCKET_H +#include "sp_server_socket.h" +#include "sp_task.h" +#include +namespace OHOS { +namespace SmartPerf { +enum class SocketConnectType { + CMD_SOCKET, + EDITOR_SOCKET, +}; + +enum class SocketErrorType { + OK, + TOKEN_CHECK_FAILED, + INIT_FAILED, + START_FAILED, + STOP_FAILED, + START_RECORD_FAILED, + STOP_RECORD_FAILED, +}; +class SpThreadSocket { +public: + static SpThreadSocket &GetInstance() + { + static SpThreadSocket instance; + return instance; + } + + std::string MapToString(std::map& dataMap) const; + std::string SplitMsg(const std::string &recvBuf) const; + void Process(ProtoType type); + SocketErrorType CheckTcpToken(const std::string& recvStr, SpServerSocket &spSocket, + const std::string& recvStrNoToken) const; + SocketErrorType CheckUdpToken(const std::string& recvStr) const; + void TypeTcp(SpServerSocket &spSocket); + void InitRecv(const std::string& recvStr, SpServerSocket &spSocket, SocketConnectType type) const; + void StartRecv(SpServerSocket &spSocket); + void StartRecvRealtime(SpServerSocket &spSocket) const; + void StopRecvRealtime(SpServerSocket &spSocket); + void StartRecvRecord(SpServerSocket &spSocket) const; + void StopRecvRecord(SpServerSocket &spSocket) const; + void SendTokenFailedMessage(SpServerSocket &socket, const std::string &message) const; + void DealMsg(const std::string& recvStr, SpServerSocket &spSocket, SocketErrorType tokenStatus); + void EditorRecv(const std::string& recvStr, const SpServerSocket &spSocket) const; + void BackDesktop() const; + void HandleMsg(SpServerSocket &spSocket); + void HeartbeatDetection(const std::string& recvBuf); + void UdpStartInitFunc(const std::string& recvBuf, SpServerSocket &spSocket); + void HandleUDPMsg(SpServerSocket &spSocket, std::map& data, std::string& retCode, + std::unordered_map::const_iterator iterator); + void SocketHeartbeat() const; + void FetchCpuStats(SpServerSocket &spSocket, std::map& data) const; + void HandleNullMsg(SpServerSocket &spSocket, SpProfiler *profiler, std::string& retCode, + const std::string& recvBuf, std::unordered_map::const_iterator iterator); + void HandleNullAddMsg(SpServerSocket &spSocket, SpProfiler *profiler, std::string& retCode, + const std::string& recvBuf, std::unordered_map::const_iterator iterator); + void UdpStartMessProcess(SpServerSocket &spSocket, SpProfiler *profiler, std::string& retCode, + const std::string& recvBuf, std::unordered_map::const_iterator iterator); + std::string SocketErrorTypeToString(SocketErrorType errorType) const; + void GetSocketPort(const std::string& buffer); + void ResetValue(std::string retCode) const; + void GetProcessIdByPkgName(std::unordered_map::const_iterator iterator); + std::string SpGetPkg(const std::string &spMsg) const; + std::string SpGetPid(const std::string &spMsg) const; + bool IsPreset(const std::string &spMsg) const; + void SetToken(const std::string& token); + std::string GetToken() const; + void SetNeedUdpToken(bool isNeed); + void ConnectAndSendFile(SpServerSocket &spSocket, const std::string filePath); + int FileSocketConnect(); + int SendFile(const std::string& filePath); + void StartHapCollecting(SpServerSocket &spSocket); + void RemoveToken(std::string &recvMessage); + +private: + bool flagRunning = false; + bool socketConnect = true; + std::string checkToken = ""; // 拉起测试时校验 + bool isNeedUdpToken = true; // 如果是hdc shell拉起,不需要校验token以兼容旧版本 + const std::string traceOriginPath = "/data/log/hiview/unified_collection/trace/special/"; + const std::string indexFilePath = "/data/local/tmp/smartperf/1/t_index_info.csv"; + const std::string gpuCounterfilePath = "/data/local/tmp/smartperfDevice"; + const std::string dubaiXpower = "/data/service/el2/100/xpower/dubai.db"; + const std::string dubaiFilePath = "/data/local/tmp/dubai/dubai.db"; + std::string tracefilePath = ""; + const std::string logFilePath = "/data/local/tmp/spdaemonlog/logfile.tar.gz"; + int sendFileSocket = -1; + int sendFileSocketPort = -1; + static const int fileSocketBufferSize = 8192; + char fileSocketBuffer[fileSocketBufferSize] = {}; + bool isSetPid = false; + SPTask &spTask = SPTask::GetInstance(); + std::thread udpStartCollect; + + std::shared_ptr taskMgr_ {nullptr}; +}; +} +} +#endif \ No newline at end of file diff --git a/smartperf_device/device_command/services/ipc/src/sp_server_socket.cpp b/smartperf_device/device_command/services/ipc/src/sp_server_socket.cpp new file mode 100644 index 0000000000000000000000000000000000000000..539ebb15e7aadf4e30d8a9bf6bdc5d6e848db0f4 --- /dev/null +++ b/smartperf_device/device_command/services/ipc/src/sp_server_socket.cpp @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include +#include +#include "include/sp_server_socket.h" +#include "include/sp_log.h" +namespace OHOS { +namespace SmartPerf { +SpServerSocket::SpServerSocket() : sockPort(0) {} + +SpServerSocket::~SpServerSocket() +{ + Close(); +} + +int SpServerSocket::Init(ProtoType type) +{ + if (type == ProtoType::TCP) { + sock = socket(AF_INET, SOCK_STREAM, 0); + sockPort = tcpPort; + } + if (type == ProtoType::UDP || type == ProtoType::UDPEX) { + sock = socket(AF_INET, SOCK_DGRAM, 0); + sockPort = (type == ProtoType::UDP ? udpPort : udpExPort); + } + if (sock < 0) { + LOGE("SpServerSocket::Init Socket Create Failed"); + return -1; + } + if (type == ProtoType::TCP) { + int optval = 1; + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0) { + LOGE("SpServerSocket::Init Socket Setsockopt failed prot(%d)", sockPort); + return -1; + } + } + local.sin_family = AF_INET; + local.sin_port = htons(sockPort); + local.sin_addr.s_addr = inet_addr("127.0.0.1"); + if (::bind(sock, reinterpret_cast(&local), sizeof(local)) < 0) { + LOGE("SpServerSocket::Init Socket Bind failed prot(%d)", sockPort); + return -1; + } + if (type == ProtoType::TCP) { + if (listen(sock, listenCount) < 0) { + LOGE("SpServerSocket::Init Socket Listen failed"); + return -1; + } + } + + LOGD("SpServerSocket::Init OK,prot(%d)", sockPort); + return 0; +} + +int SpServerSocket::Accept() +{ + connFd = accept(sock, nullptr, nullptr); + return connFd; +} + +int SpServerSocket::Sendto(const std::string &sendBuf) +{ + LOGD("SpServerSocket Sendto sendBuf(%s)", sendBuf.c_str()); + socklen_t len = sizeof(sockaddr_in); + sendto(sock, sendBuf.c_str(), sendBuf.size(), 0, reinterpret_cast(&client), len); + return 0; +} + +int SpServerSocket::Send(const std::string &sendBuf) const +{ + int sendBytes = send(connFd, sendBuf.c_str(), sendBuf.size(), 0); + if (sendBytes < 0) { + LOGE("SpServerSocket::Send Error(%d) fd(%d)", sendBytes, connFd); + return -1; + } + return 0; +} + +void SpServerSocket::Close() +{ + int optval = 1; + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); + local.sin_family = AF_INET; + local.sin_port = htons(sockPort); + local.sin_addr.s_addr = inet_addr("127.0.0.1"); + if (::bind(sock, reinterpret_cast(&local), sizeof(local)) < 0) { + LOGE("SpServerSocket::Init Socket Bind failed"); + } +} + +int SpServerSocket::Recvfrom() +{ + bzero(rbuf, sizeof(rbuf)); + socklen_t len = sizeof(sockaddr_in); + int l = recvfrom(sock, rbuf, sizeof(rbuf) - 1, 0, reinterpret_cast(&client), &len); + if (l > 0) { + std::cout << "Client:" << rbuf << std::endl; + } else { + LOGE("SpServerSocket::Recvfrom Error(%d)", l); + return -1; + } + return l; +} + +int SpServerSocket::Recv() +{ + bzero(rbuf, sizeof(rbuf)); + int l = recv(connFd, rbuf, sizeof(rbuf) - 1, 0); + if (l > 0) { + std::cout << "Client:" << rbuf << std::endl; + } else { + LOGE("SpServerSocket::recv Error(%d) fd(%d)", l, connFd); + return -1; + } + return l; +} + +std::string SpServerSocket::RecvBuf() const +{ + std::string recvBuf = rbuf; + return recvBuf; +} +} +} diff --git a/smartperf_device/device_command/services/ipc/src/sp_thread_socket.cpp b/smartperf_device/device_command/services/ipc/src/sp_thread_socket.cpp new file mode 100644 index 0000000000000000000000000000000000000000..199a5d51c04c567d4e5a88d891c15e21a7c61327 --- /dev/null +++ b/smartperf_device/device_command/services/ipc/src/sp_thread_socket.cpp @@ -0,0 +1,924 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "include/GameEvent.h" +#include "parameters.h" +#include "include/sp_csv_util.h" +#include "include/sdk_data_recv.h" +#include "include/GpuCounter.h" +#include "include/lock_frequency.h" +#include "include/sp_thread_socket.h" +#include "include/sp_profiler_factory.h" +#include "include/sp_log.h" +#include "include/sp_task.h" +#include "include/heartbeat.h" +#include "include/control_call_cmd.h" +#include "include/sp_profiler_factory.h" +#include "include/Network.h" +#include "include/startup_delay.h" +#include "include/Dubai.h" +#include "include/GetLog.h" +#include "include/RAM.h" +#include "include/FPS.h" +#include "include/hiperf.h" + +#define SMARTPERF "smartperf" +namespace OHOS { +namespace SmartPerf { +std::string g_pkgName = ""; +std::string g_pkgAndPid = ""; +std::string SpThreadSocket::MapToString(std::map& dataMap) const +{ + std::string result; + int i = 0; + std::string splitStr = ""; + for (auto iter = dataMap.cbegin(); iter != dataMap.cend(); ++iter) { + printf("%s = %s\n", iter->first.c_str(), iter->second.c_str()); + if (i > 0) { + splitStr = "$$"; + } + result += splitStr + iter->first.c_str() + "||" + iter->second.c_str(); + i++; + } + return result; +} +std::string SpThreadSocket::SplitMsg(const std::string &recvBuf) const +{ + if (recvBuf.empty()) { + LOGE("SplitMsg recvBuf is null"); + return recvBuf; + } + size_t pos = recvBuf.find("::"); + if (pos != std::string::npos) { + std::vector sps; + SPUtils::StrSplit(recvBuf, "::", sps); + if (sps.size() > 1) { + return sps[1]; + } else { + LOGE("SplitMsg sps size is zreo"); + return recvBuf; + } + } else { + return recvBuf; + } +} + +void SpThreadSocket::Process(ProtoType type) +{ + std::cout << "Socket Process called!" << std::endl; + SpServerSocket spSocket; + spSocket.Init(type); + if (type == ProtoType::TCP) { + std::cout << "Socket TCP Init called!" << std::endl; + WLOGI("Socket TCP Init called!"); + TypeTcp(spSocket); + } + if (type == ProtoType::UDP || type == ProtoType::UDPEX) { + SocketHeartbeat(); + while (socketConnect == true) { + spSocket.Recvfrom(); + HandleMsg(spSocket); + } + } + std::cout << "Socket Process finished!" << std::endl; + spSocket.Close(); +} +SocketErrorType SpThreadSocket::CheckTcpToken(const std::string& recvStr, + SpServerSocket &spSocket, const std::string& recvStrNoToken) const +{ + if (recvStr.find_last_of(":") == std::string::npos) { + if (recvStr.find("SP_daemon -editor") != std::string::npos) { + LOGI("Received string contains 'SP_daemon -editor', token check passed."); + return SocketErrorType::OK; + } else { + LOGE("Token check failed: %s", recvStrNoToken.c_str()); + return SocketErrorType::TOKEN_CHECK_FAILED; + } + } + std::string token = recvStr.substr(recvStr.find_last_of(":") + 1); + token = token.substr(0, token.find(' ')); + std::string tcpSocketToken = SpThreadSocket::GetInstance().GetToken(); + LOGD("Comparing token with TCP token..."); + if (tcpSocketToken == "" && token == "-SESSIONID") { + LOGI("Token is empty but received token is '-SESSIONID', token check passed."); + return SocketErrorType::OK; + } + if (token != tcpSocketToken) { + LOGE("Token mismatch."); + return SocketErrorType::TOKEN_CHECK_FAILED; + } + LOGD("Token match"); + return SocketErrorType::OK; +} +void SpThreadSocket::TypeTcp(SpServerSocket &spSocket) +{ + SocketHeartbeat(); + WLOGI("Socket TCP Init Finished, Wait Client Socket Connect..."); + while (socketConnect == true) { + int procFd = spSocket.Accept(); + std::cout << "Socket TCP procFd: " << procFd << std::endl; + WLOGI("Accepted socket connection, procFd: %d", procFd); + while (procFd > 0) { + int reFd = spSocket.Recv(); + if (reFd < 0) { + WLOGE("Error receiving data, reFd: %d", reFd); + break; + } + std::string recvStr = spSocket.RecvBuf(); + std::string recvStrNoToken = recvStr.substr(0, recvStr.find("::")); + LOGD("TCP recv data:%s", recvStr.c_str()); + WLOGD("Received data: %s", recvStrNoToken.c_str()); + // 解析消息 分发处理 + const SocketErrorType tokenStatus = CheckTcpToken(recvStr, spSocket, recvStrNoToken); + WLOGI("Token check status: %d", tokenStatus); + DealMsg(recvStr, spSocket, tokenStatus); + } + } +} +// TCP +void SpThreadSocket::InitRecv(const std::string& recvStr, SpServerSocket &spSocket, SocketConnectType type) const +{ + std::string errorInfo; + std::string checkStr = recvStr.substr(std::string("init::").length()); + if (!SPTask::GetInstance().CheckTcpParam(checkStr, errorInfo) && + checkStr.find(SpThreadSocket::GetInstance().GetToken()) == std::string::npos) { + WLOGE("Init error(%s)", errorInfo.c_str()); + if (type == SocketConnectType::CMD_SOCKET) { + spSocket.Send("init::False,\"error\":" + errorInfo); + } else { + spSocket.Send(std::string("init::") + SocketErrorTypeToString(SocketErrorType::INIT_FAILED)); + } + return; + } + if (recvStr.find("-lockfreq") != std::string::npos && SpThreadSocket::GetInstance().GetToken() == "") { + WLOGE("'-lockfreq' must have a valid token."); + return; + } + ErrCode code = SPTask::GetInstance().InitTask(SplitMsg(recvStr)); + if (type == SocketConnectType::CMD_SOCKET) { + spSocket.Send(std::string("init::") + ((code == ErrCode::OK) ? "True" : "False")); + WLOGI("Sent init::" + ((code == ErrCode::OK) ? "True" : "False")); + return; + } + if (code == ErrCode::OK) { + spSocket.Send("init::True"); + WLOGI("Sent init::True response"); + } else { + spSocket.Send(std::string("init::") + SocketErrorTypeToString(SocketErrorType::INIT_FAILED)); + WLOGE("Sent init::%d for failure", SocketErrorType::INIT_FAILED); + } +} +void SpThreadSocket::StartRecv(SpServerSocket &spSocket) +{ + if (flagRunning) { + spSocket.Send("SP_daemon is running"); + return; + } + auto lambdaTask = [](const std::string &data) { + std::cout << data << std::endl; + }; + ErrCode code = SPTask::GetInstance().StartTask(lambdaTask); + if (code == ErrCode::OK) { + spSocket.Send("start::True"); + flagRunning = true; + WLOGI("Sent start::True message to socket."); + } else if (code == ErrCode::FAILED) { + spSocket.Send("start::False"); + WLOGE("Sent start::False message to socket."); + return; + } + SPTask::GetInstance().StartRecord(); +} +void SpThreadSocket::StartRecvRealtime(SpServerSocket &spSocket) const +{ + auto lambdaTask = [&spSocket](const std::string &data) { spSocket.Send(data); }; + ErrCode code = SPTask::GetInstance().StartTask(lambdaTask); + if (code == ErrCode::OK) { + spSocket.Send("start::True"); + WLOGI("Sent start::True message to socket."); + } else if (code == ErrCode::FAILED) { + spSocket.Send(std::string("start::") + SocketErrorTypeToString(SocketErrorType::START_FAILED)); + WLOGE("Sent start::" + SocketErrorTypeToString(SocketErrorType::START_FAILED) + " message to socket."); + } +} +void SpThreadSocket::StopRecvRealtime(SpServerSocket &spSocket) +{ + ErrCode code = SPTask::GetInstance().StopTask(); + if (code == ErrCode::OK) { + spSocket.Send("stop::True"); + WLOGI("Sent stop::True message to socket."); + flagRunning = false; + spSocket.Close(); + } else if (code == ErrCode::FAILED) { + spSocket.Send(std::string("stop::") + SocketErrorTypeToString(SocketErrorType::STOP_FAILED)); + WLOGE("Sent stop::" + SocketErrorTypeToString(SocketErrorType::STOP_FAILED) + " message to socket."); + } +} +void SpThreadSocket::StartRecvRecord(SpServerSocket &spSocket) const +{ + ErrCode code = SPTask::GetInstance().StartRecord(); + if (code == ErrCode::OK) { + spSocket.Send("startRecord::True"); + WLOGI("Sent startRecord::True message to socket."); + } else { + spSocket.Send(std::string("startRecord::") + SocketErrorTypeToString(SocketErrorType::START_RECORD_FAILED)); + WLOGE("Sent startRecord::" + SocketErrorTypeToString(SocketErrorType::START_RECORD_FAILED) + + " message to socket."); + } +} +void SpThreadSocket::StopRecvRecord(SpServerSocket &spSocket) const +{ + ErrCode code = SPTask::GetInstance().StopRecord(); + if (code == ErrCode::OK) { + spSocket.Send("stopRecord::True"); + WLOGI("Sent stopRecord::True message to socket."); + } else { + spSocket.Send(std::string("stopRecord::") + SocketErrorTypeToString(SocketErrorType::STOP_RECORD_FAILED)); + WLOGE("Sent stopRecord::" + SocketErrorTypeToString(SocketErrorType::STOP_RECORD_FAILED) + + " message to socket."); + } +} +void SpThreadSocket::SendTokenFailedMessage(SpServerSocket &socket, const std::string &message) const +{ + if (message.find("init:::") != std::string::npos || + message.find("start:::") != std::string::npos) { + WLOGI("Skipping token check failure for init::: or start::: command."); + return; + } + const std::vector messageType = { + "init::", + "start::", + "stop::", + "startRecord::", + "stopRecord::", + }; + for (auto& it : messageType) { + if (message.find(it) != std::string::npos) { + WLOGE("Sending token check failed message for command: %s", it.c_str()); + socket.Send(it + SocketErrorTypeToString(SocketErrorType::TOKEN_CHECK_FAILED)); + return; + } + } + WLOGW("No matching command found for token check failure in message: %s", message.c_str()); +} +SocketErrorType SpThreadSocket::CheckUdpToken(const std::string& recvStr) const +{ + // 不需要校验 token + if (isNeedUdpToken == false) { + return SocketErrorType::OK; + } + // device 启动时发送,不做校验 + if (recvStr == "get_daemon_version" || recvStr.find("set_pkgName::") != std::string::npos) { + return SocketErrorType::OK; + } + // command:::token + if (recvStr.find_last_of(":::") == std::string::npos) { + WLOGE("Token check failed: %s", recvStr.c_str()); + return SocketErrorType::TOKEN_CHECK_FAILED; + } + // 提取 token + std::string token = recvStr.substr(recvStr.find_last_of(":::") + 1); + token = token.substr(0, token.find(' ')); + + std::string udpSocketToken = SpThreadSocket::GetInstance().GetToken(); + LOGD("Comparing token with Udp token..."); + // token 校验 + if (token != udpSocketToken) { + WLOGE("Token mismatch."); + return SocketErrorType::TOKEN_CHECK_FAILED; + } + LOGD("UDP token check passed"); + return SocketErrorType::OK; +} +void SpThreadSocket::DealMsg(const std::string& recvStr, SpServerSocket &spSocket, SocketErrorType tokenStatus) +{ + SocketHeartbeat(); + if (tokenStatus == SocketErrorType::TOKEN_CHECK_FAILED) { + SendTokenFailedMessage(spSocket, recvStr); + return; + } + if (recvStr.find("init:::") != std::string::npos) { + WLOGI("Processing 'init:::' command."); + InitRecv(recvStr, spSocket, SocketConnectType::CMD_SOCKET); + FPS::GetInstance().isNeedDump = true; + } else if (recvStr.find("start:::") != std::string::npos) { + WLOGI("Processing 'start:::' command."); + StartRecv(spSocket); + } else if (recvStr.find("init::") != std::string::npos) { + WLOGI("Processing 'init::' command."); + InitRecv(recvStr, spSocket, SocketConnectType::EDITOR_SOCKET); + } else if (recvStr.find("start::") != std::string::npos) { + WLOGI("Processing 'start::' command."); + StartRecvRealtime(spSocket); + } else if (recvStr.find("stop::") != std::string::npos) { + WLOGI("Processing 'stop::' command."); + SpProfilerFactory::editorFlag = false; + StopRecvRealtime(spSocket); + } else if (recvStr.find("startRecord::") != std::string::npos) { + WLOGI("Processing 'startRecord::' command."); + StartRecvRecord(spSocket); + } else if (recvStr.find("stopRecord::") != std::string::npos) { + WLOGI("Processing 'stopRecord::' command."); + SpProfilerFactory::editorFlag = false; + StopRecvRecord(spSocket); + } else if (recvStr.find("SP_daemon -editor") != std::string::npos) { + EditorRecv(recvStr, spSocket); + } else { + WLOGW("Received unknown command: %s", recvStr.c_str()); + } +} +void SpThreadSocket::EditorRecv(const std::string& recvStr, const SpServerSocket &spSocket) const +{ + std::vector vec; + size_t size = recvStr.size(); + size_t j = 0; + for (size_t i = 0; i < size; i++) { + if (recvStr[i] == ' ') { + vec.push_back(recvStr.substr(j, i - j)); + j = i + 1; + } + } + vec.push_back(recvStr.substr(j, size - j)); + const int type = 2; + if (vec[type] == "findAppPage") { + BackDesktop(); + } + OHOS::SmartPerf::ControlCallCmd controlCallCmd; + std::string result = controlCallCmd.GetResult(vec); + spSocket.Send(result); +} +void SpThreadSocket::BackDesktop() const +{ + std::string cmdResult; + std::string uinput = CMD_COMMAND_MAP.at(CmdCommand::UINPUT_BACK); + SPUtils::LoadCmd(uinput, cmdResult); +} +// UDP +void SpThreadSocket::RemoveToken(std::string &recvMessage) +{ + if (recvMessage.find(":::") != std::string::npos) { + recvMessage = recvMessage.substr(0, recvMessage.find(":::")); + } +} + +void SpThreadSocket::HandleMsg(SpServerSocket &spSocket) +{ + std::string retCode = ""; + auto iterator = MESSAGE_MAP.begin(); + while (iterator != MESSAGE_MAP.end()) { + std::string recvBuf = spSocket.RecvBuf(); + HeartbeatDetection(recvBuf); + const SocketErrorType tokenStatus = CheckUdpToken(recvBuf); + if (tokenStatus == SocketErrorType::TOKEN_CHECK_FAILED) { + std::string failStr = std::string("token failed"); + spSocket.Sendto(failStr); + spSocket.Close(); + return; + } + RemoveToken(recvBuf); + if (recvBuf.find("init::") != std::string::npos) { + LOGD("UDP recv : %s", recvBuf.c_str()); + UdpStartInitFunc(recvBuf, spSocket); + break; + } + if (!SPUtils::IsSubString(recvBuf, iterator->second)) { + ++iterator; + continue; + } + LOGD("UDP recv : %s", recvBuf.c_str()); + SpProfiler *profiler = SpProfilerFactory::GetProfilerItem(iterator->first); + if (profiler == nullptr) { + HandleNullMsg(spSocket, profiler, retCode, recvBuf, iterator); + } else { + std::map data; + if (iterator->first == MessageType::CATCH_NETWORK_TRAFFIC) { + Network::GetInstance().IsFindHap(); + profiler->ItemData(); // record the collection point for the first time,no need to return + data["network_traffic"] = "true"; + } else if (iterator->first == MessageType::GET_NETWORK_TRAFFIC) { + Network::GetInstance().IsStopFindHap(); + data = profiler->ItemData(); + data["network_traffic"] = "true"; + } else if (iterator->first == MessageType::GET_LOG) { + GetSocketPort(recvBuf); + data = profiler->ItemData(); + } else { + GetProcessIdByPkgName(iterator); + data = profiler->ItemData(); + } + HandleUDPMsg(spSocket, data, retCode, iterator); + } + break; + } +} + +void SpThreadSocket::HeartbeatDetection(const std::string& recvBuf) +{ + if (recvBuf.size() != 0) { + Heartbeat &heartbeat = Heartbeat::GetInstance(); + heartbeat.UpdatestartTime(); + } +} + +void SpThreadSocket::UdpStartInitFunc(const std::string& recvBuf, SpServerSocket &spSocket) +{ + taskMgr_ = std::make_shared(true); + auto lambdaTask = [&spSocket](const std::string &data) { spSocket.Sendto(data); }; + taskMgr_->SetIPCCallback(lambdaTask); + taskMgr_->AddTask(recvBuf); + spTask.SetAppCmd(recvBuf); + spTask.SetAppInitFlag(); + + std::string fileDir = "/data/local/tmp/smartperf/" + spTask.GetCurTaskInfo().sessionId; + spTask.CreatPath(fileDir); + taskMgr_->SetFilePath(fileDir + "/t_index_info.csv"); +} + +int SpThreadSocket::FileSocketConnect() +{ + sendFileSocket = socket(AF_INET, SOCK_STREAM, 0); + if (sendFileSocket < 0) { + WLOGE("Create log file socket failed, errno: %d", errno); + return -1; + } + struct sockaddr_in socketAddr = {0}; + socketAddr.sin_family = AF_INET; + socketAddr.sin_port = htons(sendFileSocketPort); + socketAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); + if (connect(sendFileSocket, reinterpret_cast(&socketAddr), sizeof(socketAddr)) < 0) { + WLOGE("Connect log file socket failed, errno: %d", errno); + return -1; + } + WLOGI("Connect log file socket success, socket: %d", sendFileSocket); + return sendFileSocket; +} + +int SpThreadSocket::SendFile(const std::string& filePath) +{ + char filePathChar[PATH_MAX] = {0x00}; + if ((realpath(filePath.c_str(), filePathChar) == nullptr)) { + WLOGE("%s is not exist.", filePath.c_str()); + return -1; + } + std::ifstream logFile(filePathChar, std::ios::binary); + if (!logFile.is_open()) { + WLOGE("Open log file failed"); + close(sendFileSocket); + sendFileSocket = -1; + return -1; + } + WLOGI("logfile exists, sending..."); + logFile.seekg(0, std::ios::end); + std::streamsize fileSize = logFile.tellg(); + logFile.seekg(0, std::ios::beg); + std::streamsize totalSent = 0; + while (!logFile.eof()) { + logFile.read(fileSocketBuffer, sizeof(fileSocketBuffer)); + std::streamsize bytesRead = logFile.gcount(); + ssize_t bytesSent = send(sendFileSocket, fileSocketBuffer, bytesRead, 0); + if (bytesSent < 0) { + WLOGE("Send log file failed"); + logFile.close(); + close(sendFileSocket); + sendFileSocket = -1; + return -1; + } + totalSent += bytesSent; + if (bytesSent != bytesRead) { + WLOGE("Incomplete send: sent %zd bytes out of %zd", bytesSent, bytesRead); + logFile.close(); + close(sendFileSocket); + sendFileSocket = -1; + return -1; + } + } + if (totalSent != fileSize) { + WLOGE("File size mismatch: sent %zd bytes, file size %zd", totalSent, fileSize); + return -1; + } + logFile.close(); + close(sendFileSocket); + sendFileSocket = -1; + WLOGI("Send log file success, bytes: %zd", totalSent); + return 0; +} + +void SpThreadSocket::ConnectAndSendFile(SpServerSocket &spSocket, const std::string filePath) +{ + if (filePath.empty()) { + WLOGE("Connect filePath does not exist."); + return; + } + if (sendFileSocketPort == -1) { + return; + } + std::thread sendSizeThread([&spSocket, filePath]() { + size_t fileSize = SPUtils::GetFileSize(filePath); + if (fileSize == 0) { + LOGE("UDP ConnectAndSendFile recv GetFileSize fileSize: (%d)", fileSize); + return; + } + std::string sendFileSizeMsg = "SendFileSize:::" + std::to_string(fileSize); + LOGD("UDP START sendFileSizeMsg = %s", sendFileSizeMsg.c_str()); + spSocket.Sendto(sendFileSizeMsg); + LOGD("UDP Sendto sendFileSizeMsg = %s", sendFileSizeMsg.c_str()); + }); + std::thread sendFileThread([this, filePath]() { + int fileSocket = -1; + int connectCount = 0; + const int maxTryCount = 2; + + while (fileSocket < 0) { + WLOGI("Connect file log socket, try times: %d", connectCount + 1); + if (connectCount > maxTryCount) { + WLOGE("Connect file log socket failed"); + return; + } + connectCount++; + fileSocket = FileSocketConnect(); + } + + int ret = SendFile(filePath); + if (ret < 0) { + WLOGE("Failed to send file"); + return; + } + }); + + sendSizeThread.join(); + sendFileThread.join(); +} + +void SpThreadSocket::HandleUDPMsg(SpServerSocket &spSocket, std::map& data, + std::string& retCode, std::unordered_map::const_iterator iterator) +{ + std::cout << "iterator->first: " << static_cast(iterator->first) << std::endl; + if (iterator->first == MessageType::GET_CUR_FPS) { + FPS::GetInstance().isLowCurFps = true; + std::string resultfps = "vfps||"; + for (auto iter = data.cbegin(); iter != data.cend(); ++iter) { + if (iter->first != "fpsJitters") { + std::string temp = iter->second + "@@"; + resultfps += std::string(temp.c_str()); + } + } + spSocket.Sendto(resultfps); + LOGD("UDP send Cur_resultfps = %s", resultfps.c_str()); + } else if (iterator->first == MessageType::GET_CPU_FREQ_LOAD) { + FetchCpuStats(spSocket, data); + } else if (iterator->first == MessageType::GET_LOG) { + ConnectAndSendFile(spSocket, logFilePath); + GetLog::GetInstance().RemoveLogFile(); + } else { + retCode = MapToString(data); + spSocket.Sendto(retCode); + LOGD("UDP send retCode = %s", retCode.c_str()); + } +} +void SpThreadSocket::SocketHeartbeat() const +{ + Heartbeat &heartbeat = Heartbeat::GetInstance(); + heartbeat.UpdatestartTime(); +} +void SpThreadSocket::FetchCpuStats(SpServerSocket &spSocket, std::map& data) const +{ + std::string resultCpuFrequency = ""; + std::string resultCpuUsage = ""; + std::string resultCpu = ""; + int cpuFrequencyNum = 0; + int cpuUsageNum = 0; + int cpuFlag = 1; + while (cpuFlag) { + resultCpuFrequency = "cpu" + std::to_string(cpuFrequencyNum) + "Frequency"; + resultCpuUsage = "cpu" + std::to_string(cpuUsageNum) + "Usage"; + auto iterCpuFrequency = data.find(resultCpuFrequency); + auto iterCpuUsage = data.find(resultCpuUsage); + if (iterCpuFrequency != data.end()) { + resultCpuFrequency += "||" + iterCpuFrequency->second; + resultCpu += "$$" + resultCpuFrequency; + cpuFrequencyNum++; + } else { + cpuFlag = 0; + } + if (iterCpuUsage != data.end()) { + resultCpuUsage += "||" + iterCpuUsage->second; + resultCpu += "$$" + resultCpuUsage; + cpuUsageNum++; + } else { + cpuFlag = 0; + } + } + spSocket.Sendto(resultCpu); + LOGD("UDP send resultCpu = %s", resultCpu.c_str()); +} +void SpThreadSocket::HandleNullMsg(SpServerSocket &spSocket, SpProfiler *profiler, std::string& retCode, + const std::string& recvBuf, std::unordered_map::const_iterator iterator) +{ + if (iterator->first == MessageType::SET_PKG_NAME) { + isSetPid = false; + retCode = SplitMsg(recvBuf); + if (recvBuf.find(SMARTPERF) != std::string::npos && retCode.find(SMARTPERF) != std::string::npos) { + Dubai::dubaiPkgName = retCode; + LOGD("UDP send smartperf: (%s)", Dubai::dubaiPkgName.c_str()); + } else { + if (retCode.find("$") != std::string::npos) { + g_pkgAndPid = retCode; + g_pkgName = SpGetPkg(g_pkgAndPid); + } else { + g_pkgName = retCode; + } + std::thread([this]() { this->ResetValue(g_pkgName); }).detach(); + LOGD("HandleNullMsg pkgName: (%s)", g_pkgName.c_str()); + } + spSocket.Sendto(retCode); + LOGD("UDP send PkgName = %s", retCode.c_str()); + } else if (profiler == nullptr && (iterator->first == MessageType::GET_APP_TYPE)) { + retCode = SplitMsg(recvBuf); + std::thread([this, retCode]() { this->ResetValue(retCode); }).detach(); + } else if (profiler == nullptr && (iterator->first == MessageType::GET_DAEMON_VERSION)) { + retCode = "Version: " + SPUtils::GetVersion(); + spSocket.Sendto(retCode); + } else if (iterator->first == MessageType::CATCH_TRACE_CONFIG || + iterator->first == MessageType::CATCH_TRACE_CMD) { + SpProfilerFactory::SetByTrace(SplitMsg(recvBuf)); + } else if (iterator->first == MessageType::GET_CPU_NUM) { + retCode = SPUtils::GetCpuNum(); + spSocket.Sendto(retCode); + LOGD("UDP send cpuNum = %s", retCode.c_str()); + } else if (iterator->first == MessageType::BACK_TO_DESKTOP) { + BackDesktop(); + } else { + HandleNullAddMsg(spSocket, profiler, retCode, recvBuf, iterator); + } +} + +void SpThreadSocket::GetProcessIdByPkgName(std::unordered_map::const_iterator iterator) +{ + if (iterator->first == MessageType::GET_FPS_AND_JITTERS || iterator->first == MessageType::GET_CUR_FPS || + iterator->first == MessageType::GET_RAM_INFO) { + if (!SpProfilerFactory::editorFlag && isSetPid == false) { + FPS::GetInstance().isHistoryHap = true; + std::string pkgName = g_pkgName; + std::string pkgAndPid = g_pkgAndPid; + LOGD("SpProfilerFactory::g_pkgName(%s)", g_pkgName.c_str()); + std::string processId = ""; + std::string processIds = ""; + FPS::GetInstance().isPreset = IsPreset(pkgAndPid); + if (FPS::GetInstance().isPreset) { + processId = SpGetPid(pkgAndPid); + } else { + OHOS::SmartPerf::StartUpDelay sp; + processId = sp.GetPidByPkg(pkgName, &processIds); + } + SpProfilerFactory::SetProfilerPidByPkg(processId, processIds); + SpProfilerFactory::SetProfilerPkg(pkgName); + isSetPid = true; + } + } +} + +void SpThreadSocket::ResetValue(std::string retCode) const +{ + FPS::GetInstance().isGameApp = SPUtils::GetIsGameApp(retCode); + RAM::GetInstance().SetHapFirstFlag(); +} +void SpThreadSocket::HandleNullAddMsg(SpServerSocket &spSocket, SpProfiler *profiler, std::string& retCode, + const std::string& recvBuf, std::unordered_map::const_iterator iterator) +{ + Dubai &db = Dubai::GetInstance(); + if (iterator->first == MessageType::START_DUBAI_DB) { + std::thread dStart([&db]() { db.CallBeginAndFinish(); }); + dStart.detach(); + } else if (iterator->first == MessageType::SET_DUBAI_DB) { + GetSocketPort(recvBuf); + db.CallBeginAndFinish(); + FPS::GetInstance().isLowCurFps = false; + db.MoveDubaiDb(dubaiXpower); + ConnectAndSendFile(spSocket, dubaiFilePath); + retCode = "get_dubai_db"; + LOGD("UDP send GetDubaiDb Message: (%s)", retCode.c_str()); + spSocket.Sendto(retCode); + LOGD("UDP send DuBai get finish"); + } else if (iterator->first == MessageType::CHECK_UDP_STATUS) { + retCode = "UDP status is normal"; + spSocket.Sendto(retCode); + LOGD("UDP status is normal"); + } else if (iterator->first == MessageType::SAVE_GPU_COUNTER) { + GetSocketPort(recvBuf); + std::unique_lock lock(GpuCounter::GetInstance().GetGpuCounterLock()); + ConnectAndSendFile(spSocket, gpuCounterfilePath + "/gpu_counter.csv"); + } else if (iterator->first == MessageType::CATCH_TRACE_FINISH) { + tracefilePath = ""; + GetSocketPort(recvBuf); + ConnectAndSendFile(spSocket, tracefilePath); + } else if (iterator->first == MessageType::APP_STOP_COLLECT) { + if (taskMgr_ != nullptr) { + // UDP (device) 停止时,设置GPU_COUNTER保存路径 + SPUtils::CreateDir(gpuCounterfilePath); + GpuCounter::GetInstance().SetSavePathDirectory(gpuCounterfilePath); + taskMgr_->SetHapFlag(false); + taskMgr_->Stop(); + retCode = Hiperf::GetInstance().ReturnHiperfData(); + spSocket.Sendto(retCode); + taskMgr_->WriteToCSV(); + } + spTask.ClearStopFlag(); + } else { + UdpStartMessProcess(spSocket, profiler, retCode, recvBuf, iterator); + } +} + +void SpThreadSocket::UdpStartMessProcess(SpServerSocket &spSocket, SpProfiler *profiler, std::string& retCode, + const std::string& recvBuf, std::unordered_map::const_iterator iterator) +{ + if (iterator->first == MessageType::APP_START_COLLECT) { + if (taskMgr_ != nullptr) { + taskMgr_->AddTask(&SdkDataRecv::GetInstance(), false); + } + StartHapCollecting(spSocket); + } else if (iterator->first == MessageType::APP_RECEIVE_DATA_ON) { + if (taskMgr_ != nullptr) { + LOGD("Start to display data in real time"); + taskMgr_->SetHapFlag(true); + taskMgr_->EnableIPCCallback(); + } + } else if (iterator->first == MessageType::APP_RECEIVE_DATA_OFF) { + if (taskMgr_ != nullptr) { + LOGD("Real time data display ends"); + taskMgr_->DisableIPCCallback(); + } + } else if (iterator->first == MessageType::APP_PAUSE_COLLECT) { + if (taskMgr_ != nullptr) { + LOGD("Pause Collection"); + SPUtils::CreateDir(gpuCounterfilePath); + GpuCounter::GetInstance().SetSavePathDirectory(gpuCounterfilePath); + GpuCounter::GetInstance().SetIsPause(true); + taskMgr_->Stop(true); + } + } else if (iterator->first == MessageType::APP_RESUME_COLLECT) { + LOGD("Resuming Collection"); + StartHapCollecting(spSocket); + GpuCounter::GetInstance().SetIsPause(false); + } else if (iterator->first == MessageType::GET_INDEX_INFO) { + GetSocketPort(recvBuf); + ConnectAndSendFile(spSocket, indexFilePath); + } else { + retCode = iterator->second; + spSocket.Sendto(retCode); + LOGD("UDP sendData: (%s)", retCode.c_str()); + } +} +std::string SpThreadSocket::SocketErrorTypeToString(SocketErrorType errorType) const +{ + switch (errorType) { + case SocketErrorType::OK: + return "OK"; + case SocketErrorType::TOKEN_CHECK_FAILED: + return "TOKEN_CHECK_FAILED"; + case SocketErrorType::INIT_FAILED: + return "INIT_FAILED"; + case SocketErrorType::START_FAILED: + return "START_FAILED"; + case SocketErrorType::STOP_FAILED: + return "STOP_FAILED"; + case SocketErrorType::START_RECORD_FAILED: + return "START_RECORD_FAILED"; + case SocketErrorType::STOP_RECORD_FAILED: + return "STOP_RECORD_FAILED"; + default: + return "UNKNOWN"; + } +} +void SpThreadSocket::GetSocketPort(const std::string& buffer) +{ + if (buffer.find("::") != std::string::npos) { + std::string portStr = buffer.substr(buffer.find("::") + 2); + std::string fileName = ""; + if (portStr.find(":::") != std::string::npos) { + portStr = portStr.substr(0, portStr.find(":::")); + } + + if (portStr.find("$") != std::string::npos) { + fileName = portStr.substr(portStr.find("$") + 1); + portStr = portStr.substr(0, portStr.find("$")); + tracefilePath = traceOriginPath + fileName; + } + + int port = SPUtilesTye::StringToSometype(portStr); + if (port <= 0) { + WLOGE("Invalid port number: %d", port); + sendFileSocketPort = -1; + } else { + WLOGI("Get File log UDP message received, port is %d", port); + sendFileSocket = -1; + sendFileSocketPort = port; + } + } else { + WLOGE("Get File log UDP message received, but port is not found"); + sendFileSocketPort = -1; + } +} +std::string SpThreadSocket::SpGetPkg(const std::string &spMsg) const +{ + if (spMsg.empty()) { + return spMsg; + } + size_t pos = spMsg.find("$"); + if (pos != std::string::npos) { + std::vector sps; + SPUtils::StrSplit(spMsg, "$", sps); + if (sps.size() > 1) { + return sps[0]; + } else { + return spMsg; + } + } else { + return spMsg; + } +} + +std::string SpThreadSocket::SpGetPid(const std::string &spMsg) const +{ + if (spMsg.empty()) { + LOGE("spMsg is null"); + return spMsg; + } + size_t pos = spMsg.find("$"); + if (pos != std::string::npos) { + std::vector sps; + SPUtils::StrSplit(spMsg, "$", sps); + if (sps.size() > 1) { + return sps[1]; + } else { + LOGE("SpGetPid sps size is zreo"); + return ""; + } + } else { + return ""; + } +} + +bool SpThreadSocket::IsPreset(const std::string &spMsg) const +{ + return spMsg.find("$") != std::string::npos; +} + +void SpThreadSocket::SetToken(const std::string& token) +{ + checkToken = token; +} + +std::string SpThreadSocket::GetToken() const +{ + return checkToken; +} + +void SpThreadSocket::SetNeedUdpToken(bool isNeed) +{ + isNeedUdpToken = isNeed; +} + +void SpThreadSocket::StartHapCollecting(SpServerSocket &spSocket) +{ + LOGD("UDP START Task starting..."); + RAM &ram = RAM::GetInstance(); + ram.SetFirstFlag(); + if (udpStartCollect.joinable()) { + udpStartCollect.join(); + } + udpStartCollect = std::thread([this]() { + if (taskMgr_ == nullptr) { + return; + } + taskMgr_->Start(); + taskMgr_->SetRecordState(true); + taskMgr_->Wait(); + LOGD("Data collecting thread exiting."); + }); + return; +} +} +} \ No newline at end of file