• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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