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 25using PtJson = panda::ecmascript::tooling::PtJson; 26using Result = panda::ecmascript::tooling::Result; 27namespace OHOS::ArkCompiler::Toolchain { 28uv_async_t* g_socketSignal; 29void SocketMessageThread(void *arg) 30{ 31 int sessionId = *(uint32_t *)arg; 32 Session *session = SessionManager::getInstance().GetSessionById(sessionId); 33 34 session->SocketMessageLoop(); 35} 36 37Session::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 43void 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 61int 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 92int Session::Start() 93{ 94 if (CreateSocket()) { 95 return -1; 96 } 97 98 uv_thread_create(&socketTid_, SocketMessageThread, &sessionId_); 99 return 0; 100} 101 102int Session::Stop() 103{ 104 cliSocket_.Close(); 105 return 0; 106} 107 108int 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 119int 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 141int SessionManager::CreateDefaultSession(std::string& sockInfo) 142{ 143 return CreateSessionById(0, sockInfo); 144} 145 146int 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 163int 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 177int 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 187void 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 197int 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}