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