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