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
19 namespace OHOS::ArkCompiler::Toolchain {
20 uv_async_t* g_inputSignal;
21 uv_async_t* g_releaseHandle;
22 std::string g_inputStr = "";
23 std::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" };
33 std::vector<std::string> g_noRecvCmds = { "cpuprofile-enable", "cp-enable", "cpuprofile-disable", "cp-disable",
34 "cpuprofile-stop", "cp-stop" };
35 std::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
CreateServer(void* arg)39 void CreateServer(void* arg)
40 {
41 TcpServer::getInstance().StartTcpServer(arg);
42 }
43
CloseServer()44 void TcpServer::CloseServer()
45 {
46 if (uv_is_active(reinterpret_cast<uv_handle_t*>(g_releaseHandle))) {
47 uv_async_send(g_releaseHandle);
48 }
49 }
50
ServerConnect()51 void 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
SendCommand(std::string inputStr)90 void 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
StartTcpServer([[maybe_unused]] void* arg)119 void 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
TcpServerWrite(std::string msg)147 void 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
CreateTcpServer([[maybe_unused]] void* arg)183 int TcpServer::CreateTcpServer([[maybe_unused]] void* arg)
184 {
185 uv_thread_create(&serverTid_, CreateServer, nullptr);
186 return 0;
187 }
188
FindCommand(std::vector<std::string> cmds, std::string cmd)189 bool 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