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#include "tooling/client/tcpServer/tcp_server.h" 16 17#include "tooling/utils/utils.h" 18 19namespace OHOS::ArkCompiler::Toolchain { 20uv_async_t* g_inputSignal; 21uv_async_t* g_releaseHandle; 22std::string g_inputStr = ""; 23std::vector<std::string> g_allCmds = { "allocationtrack", "at", "allocationtrack-stop", "at-stop", "heapdump", "hd", 24 "heapprofiler-enable", "hp-enable", "heapprofiler-disable", "hp-disable", "sampling", "sampling", "sampling-stop", 25 "sampling-stop", "collectgarbage", "gc", "cpuprofile", "cp", "cpuprofile-stop", "cp-stop", "cpuprofile-enable", 26 "cp-enable", "cpuprofile-disable", "cp-disable", "cpuprofile-show", "cp-show", "cpuprofile-setSamplingInterval", 27 "cp-ssi", "runtime-enable", "rt-enable", "heapusage", "hu", "break", "b", "backtrack", "bt", "continue", "c", 28 "delete", "d", "disable", "disable", "display", "display", "enable", "enable", "finish", "fin", "frame", "f", 29 "help", "h", "ignore", "ig", "infobreakpoints", "infob", "infosource", "infos", "jump", "j", "list", "l", "next", 30 "n", "print", "p", "ptype", "ptype", "run", "r", "setvar", "sv", "step", "s", "undisplay", "undisplay", "watch", 31 "wa", "resume", "resume", "showstack", "ss", "step-into", "si", "step-out", "so", "step-over", "sov", 32 "runtime-disable", "rt-disable" }; 33std::vector<std::string> g_noRecvCmds = { "cpuprofile-enable", "cp-enable", "cpuprofile-disable", "cp-disable", 34 "cpuprofile-stop", "cp-stop" }; 35std::vector<std::string> g_inputOnMessages = { "b", "break", "bt", "backtrack", "d", "delete", "display", "fin", 36 "finish", "f", "frame", "h", "help", "ig", "ignore", "infob", "infobreakpoints", "infos", "infosource", "j", "jump", 37 "l", "list", "n", "next", "ptype", "s", "step", "ss", "showstack", "watch", "wa" }; 38 39void CreateServer(void* arg) 40{ 41 TcpServer::getInstance().StartTcpServer(arg); 42} 43 44void TcpServer::CloseServer() 45{ 46 if (uv_is_active(reinterpret_cast<uv_handle_t*>(g_releaseHandle))) { 47 uv_async_send(g_releaseHandle); 48 } 49} 50 51void TcpServer::ServerConnect() 52{ 53 isServerActive = 1; 54 struct sockaddr_in saddr; 55 saddr.sin_family = AF_INET; 56 saddr.sin_addr.s_addr = INADDR_ANY; 57 saddr.sin_port = htons(9999); // 9999: tcp bind port 58 59 lfd = socket(AF_INET, SOCK_STREAM, 0); 60 if (lfd == -1) { 61 std::cout << "socket failed" << std::endl; 62 CloseServer(); 63 return; 64 } 65 66 int ret = bind(lfd, (struct sockaddr*)&saddr, sizeof(saddr)); 67 if (ret == -1) { 68 std::cout << "bind failed" << std::endl; 69 CloseServer(); 70 return; 71 } 72 73 ret = listen(lfd, 6); // 6: Number of backlogs 74 if (ret == -1) { 75 std::cout << "listen failed" << std::endl; 76 CloseServer(); 77 return; 78 } 79 80 struct sockaddr_in clientaddr; 81 socklen_t len = sizeof(clientaddr); 82 cfd = accept(lfd, (struct sockaddr*)&clientaddr, &len); 83 if (cfd == -1) { 84 std::cout << "accept failed" << std::endl; 85 CloseServer(); 86 return; 87 } 88} 89 90void TcpServer::SendCommand(std::string inputStr) 91{ 92 inputStr.erase(0, inputStr.find_first_not_of(" ")); 93 if (inputStr.empty()) { 94 std::cout << "cmd is empty" << std::endl; 95 return; 96 } 97 98 if (uv_is_active(reinterpret_cast<uv_handle_t*>(g_inputSignal))) { 99 uint32_t len = inputStr.length(); 100 if (len < 0) { 101 CloseServer(); 102 return; 103 } 104 char* msg = (char*)malloc(len + 1); 105 if (msg == nullptr) { 106 return; 107 } 108 if (strncpy_s(msg, len + 1, inputStr.c_str(), len) != 0) { 109 free(msg); 110 CloseServer(); 111 return; 112 } 113 g_inputSignal->data = std::move(msg); 114 uv_async_send(g_inputSignal); 115 } 116 return; 117} 118 119void TcpServer::StartTcpServer([[maybe_unused]] void* arg) 120{ 121 ServerConnect(); 122 123 const char* data = "connect success"; 124 write(cfd, data, strlen(data)); 125 int num = 0; 126 do { 127 char recvBuf[1024] = { 0 }; 128 num = read(cfd, recvBuf, sizeof(recvBuf)); 129 if (num < 0) { 130 std::cout << "read failed" << std::endl; 131 } else if (num > 0) { 132 g_inputStr = std::string(recvBuf); 133 SendCommand(recvBuf); 134 TcpServerWrite(); 135 } else if (num == 0) { 136 std::cout << "clinet closed" << std::endl; 137 } 138 } while (num > 0); 139 140 close(cfd); 141 close(lfd); 142 143 CloseServer(); 144 return; 145} 146 147void TcpServer::TcpServerWrite(std::string msg) 148{ 149 if (g_inputStr.empty()) { 150 return; 151 } 152 153 std::vector<std::string> cliCmdStr = Utils::SplitString(g_inputStr, " "); 154 if (!FindCommand(g_allCmds, cliCmdStr[0])) { 155 g_inputStr = "error cmd"; 156 write(cfd, g_inputStr.c_str(), strlen(g_inputStr.c_str())); 157 g_inputStr.clear(); 158 return; 159 } 160 if (msg == "inner") { 161 if (FindCommand(g_noRecvCmds, cliCmdStr[0])) { 162 write(cfd, g_inputStr.c_str(), strlen(g_inputStr.c_str())); 163 g_inputStr.clear(); 164 } 165 } else if (msg == "InputOnMessage") { 166 if (FindCommand(g_inputOnMessages, cliCmdStr[0])) { 167 write(cfd, g_inputStr.c_str(), strlen(g_inputStr.c_str())); 168 g_inputStr.clear(); 169 } 170 } else if (msg == "SocketOnMessage") { 171 if (FindCommand(g_inputOnMessages, cliCmdStr[0])) { 172 return; 173 } 174 if (g_inputStr.empty()) { 175 return; 176 } 177 write(cfd, g_inputStr.c_str(), strlen(g_inputStr.c_str())); 178 g_inputStr.clear(); 179 } 180 return; 181} 182 183int TcpServer::CreateTcpServer([[maybe_unused]] void* arg) 184{ 185 uv_thread_create(&serverTid_, CreateServer, nullptr); 186 return 0; 187} 188 189bool TcpServer::FindCommand(std::vector<std::string> cmds, std::string cmd) 190{ 191 return find(cmds.begin(), cmds.end(), cmd) != cmds.end(); 192} 193} // namespace OHOS::ArkCompiler::Toolchain