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