1 /*
2 * Copyright (c) 2023 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
16 #include "tooling/client/session/session.h"
17
18 #include "common/log_wrapper.h"
19 #include "tooling/client/manager/message_manager.h"
20 #include "tooling/base/pt_json.h"
21 #include "tooling/utils/utils.h"
22
23 #include <iomanip>
24
25 using PtJson = panda::ecmascript::tooling::PtJson;
26 using Result = panda::ecmascript::tooling::Result;
27 namespace OHOS::ArkCompiler::Toolchain {
28 uv_async_t* g_socketSignal;
SocketMessageThread(void * arg)29 void SocketMessageThread(void *arg)
30 {
31 int sessionId = *(uint32_t *)arg;
32 Session *session = SessionManager::getInstance().GetSessionById(sessionId);
33
34 session->SocketMessageLoop();
35 }
36
Session(uint32_t sessionId,std::string & sockInfo)37 Session::Session(uint32_t sessionId, std::string& sockInfo)
38 : sessionId_(sessionId), sockInfo_(sockInfo), domainManager_(sessionId), breakpoint_(sessionId),
39 stackManager_(sessionId), variableManager_(sessionId), sourceManager_(sessionId), watchManager_(sessionId)
40 {
41 }
42
SocketMessageLoop()43 void Session::SocketMessageLoop()
44 {
45 while (cliSocket_.IsConnected()) {
46 std::string decMessage = cliSocket_.Decode();
47 uint32_t len = decMessage.length();
48 if (len == 0) {
49 continue;
50 }
51 LOGI("arkdb [%{public}u] message = %{public}s", sessionId_, decMessage.c_str());
52
53 MessageManager::getInstance().MessagePush(sessionId_, decMessage);
54
55 if (uv_is_active(reinterpret_cast<uv_handle_t*>(g_socketSignal))) {
56 uv_async_send(g_socketSignal);
57 }
58 }
59 }
60
CreateSocket()61 int Session::CreateSocket()
62 {
63 uint32_t port = 0;
64 if (Utils::StrToUInt(sockInfo_.c_str(), &port)) {
65 if ((port <= 0) || (port >= 65535)) { // 65535: max port
66 LOGE("arkdb:InitToolchainWebSocketForPort the port = %{public}d is wrong.", port);
67 return -1;
68 }
69 if (!cliSocket_.InitToolchainWebSocketForPort(port, 5)) { // 5: five times
70 LOGE("arkdb:InitToolchainWebSocketForPort failed");
71 return -1;
72 }
73 } else {
74 if (!cliSocket_.InitToolchainWebSocketForSockName(sockInfo_)) {
75 LOGE("arkdb:InitToolchainWebSocketForSockName failed");
76 return -1;
77 }
78 }
79
80 if (!cliSocket_.ClientSendWSUpgradeReq()) {
81 LOGE("arkdb:ClientSendWSUpgradeReq failed");
82 return -1;
83 }
84 if (!cliSocket_.ClientRecvWSUpgradeRsp()) {
85 LOGE("arkdb:ClientRecvWSUpgradeRsp failed");
86 return -1;
87 }
88
89 return 0;
90 }
91
Start()92 int Session::Start()
93 {
94 if (CreateSocket()) {
95 return -1;
96 }
97
98 uv_thread_create(&socketTid_, SocketMessageThread, &sessionId_);
99 return 0;
100 }
101
Stop()102 int Session::Stop()
103 {
104 cliSocket_.Close();
105 return 0;
106 }
107
CreateSessionById(uint32_t sessionId,std::string & sockInfo)108 int SessionManager::CreateSessionById(uint32_t sessionId, std::string& sockInfo)
109 {
110 sessions_[sessionId] = std::make_unique<Session>(sessionId, sockInfo);
111 if (sessions_[sessionId]->Start()) {
112 sessions_[sessionId] = nullptr;
113 return -1;
114 }
115
116 return 0;
117 }
118
CreateNewSession(std::string & sockInfo)119 int SessionManager::CreateNewSession(std::string& sockInfo)
120 {
121 uint32_t sessionId = MAX_SESSION_NUM;
122 for (uint32_t i = 0; i < MAX_SESSION_NUM; ++i) {
123 if (sessions_[i] == nullptr) {
124 if (sessionId == MAX_SESSION_NUM) {
125 sessionId = i;
126 }
127 continue;
128 }
129 if (sessions_[i]->GetSockInfo() == sockInfo) {
130 return -1;
131 }
132 }
133
134 if (sessionId < MAX_SESSION_NUM) {
135 return CreateSessionById(sessionId, sockInfo);
136 }
137
138 return -1;
139 }
140
CreateDefaultSession(std::string & sockInfo)141 int SessionManager::CreateDefaultSession(std::string& sockInfo)
142 {
143 return CreateSessionById(0, sockInfo);
144 }
145
DelSessionById(uint32_t sessionId)146 int SessionManager::DelSessionById(uint32_t sessionId)
147 {
148 Session *session = GetSessionById(sessionId);
149 if (session == nullptr) {
150 return -1;
151 }
152 session->Stop();
153 sessions_[sessionId] = nullptr;
154
155 if (sessionId == currentSessionId_) {
156 currentSessionId_ = 0;
157 std::cout << "session switch to 0" << std::endl;
158 }
159
160 return 0;
161 }
162
SessionList()163 int SessionManager::SessionList()
164 {
165 for (uint32_t i = 0; i < MAX_SESSION_NUM; ++i) {
166 if (sessions_[i] != nullptr) {
167 std::string flag = (i == currentSessionId_) ? "* " : " ";
168 std::string sockState = sessions_[i]->GetSocketStateString();
169 std::cout << flag << i << ": ";
170 std::cout << std::setw(32) << std::left << sessions_[i]->GetSockInfo(); // 32: max length of socket info
171 std::cout << sockState << std::endl;
172 }
173 }
174 return 0;
175 }
176
SessionSwitch(uint32_t sessionId)177 int SessionManager::SessionSwitch(uint32_t sessionId)
178 {
179 Session *session = GetSessionById(sessionId);
180 if (session == nullptr) {
181 return -1;
182 }
183 currentSessionId_ = sessionId;
184 return 0;
185 }
186
CmdForAllSessions(CmdForAllCB callback)187 void SessionManager::CmdForAllSessions(CmdForAllCB callback)
188 {
189 for (uint32_t sessionId = 0; sessionId < MAX_SESSION_NUM; ++sessionId) {
190 if (sessions_[sessionId] != nullptr) {
191 std::cout << "Executing command in session " << sessionId << ":" << std::endl;
192 callback(sessionId);
193 }
194 }
195 }
196
CreateTestSession(std::string & sockInfo)197 int SessionManager::CreateTestSession(std::string& sockInfo)
198 {
199 uint32_t sessionId = 0;
200 sessions_[sessionId] = std::make_unique<Session>(sessionId, sockInfo);
201 if (sessions_[sessionId]->CreateSocket()) {
202 sessions_[sessionId] = nullptr;
203 return -1;
204 }
205
206 return 0;
207 }
208 }