1e509ee18Sopenharmony_ci/*
2e509ee18Sopenharmony_ci * Copyright (c) 2022 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 "ws_server.h"
17e509ee18Sopenharmony_ci
18e509ee18Sopenharmony_ci#include <fstream>
19e509ee18Sopenharmony_ci#include <iostream>
20e509ee18Sopenharmony_ci#include <shared_mutex>
21e509ee18Sopenharmony_ci#include <sys/types.h>
22e509ee18Sopenharmony_ci#include <unistd.h>
23e509ee18Sopenharmony_ci
24e509ee18Sopenharmony_ci#include "common/log_wrapper.h"
25e509ee18Sopenharmony_ci#include "websocket/server/websocket_server.h"
26e509ee18Sopenharmony_ci
27e509ee18Sopenharmony_cinamespace OHOS::ArkCompiler::Toolchain {
28e509ee18Sopenharmony_cistd::shared_mutex g_mutex;
29e509ee18Sopenharmony_ci
30e509ee18Sopenharmony_ci// defined in .cpp file for WebSocketServer forward declaration
31e509ee18Sopenharmony_ciWsServer::WsServer(const DebugInfo& debugInfo, const std::function<void(std::string&&)>& onMessage)
32e509ee18Sopenharmony_ci    : debugInfo_(debugInfo), wsOnMessage_(onMessage)
33e509ee18Sopenharmony_ci{}
34e509ee18Sopenharmony_ci
35e509ee18Sopenharmony_ciWsServer::~WsServer() = default;
36e509ee18Sopenharmony_ci
37e509ee18Sopenharmony_civoid WsServer::RunServer()
38e509ee18Sopenharmony_ci{
39e509ee18Sopenharmony_ci    {
40e509ee18Sopenharmony_ci        std::lock_guard<std::mutex> lock(wsMutex_);
41e509ee18Sopenharmony_ci        if (terminateExecution_) {
42e509ee18Sopenharmony_ci            LOGE("WsServer has been terminated unexpectedly");
43e509ee18Sopenharmony_ci            return;
44e509ee18Sopenharmony_ci        }
45e509ee18Sopenharmony_ci        webSocket_ = std::make_unique<WebSocketServer>();
46e509ee18Sopenharmony_ci#if !defined(OHOS_PLATFORM)
47e509ee18Sopenharmony_ci        LOGI("WsSever Runsever: Init tcp websocket %{public}d", debugInfo_.port);
48e509ee18Sopenharmony_ci        if (!webSocket_->InitTcpWebSocket(debugInfo_.port)) {
49e509ee18Sopenharmony_ci            return;
50e509ee18Sopenharmony_ci        }
51e509ee18Sopenharmony_ci#else
52e509ee18Sopenharmony_ci        int runSeverInOldProcess = -2;
53e509ee18Sopenharmony_ci        if (debugInfo_.socketfd == runSeverInOldProcess) {
54e509ee18Sopenharmony_ci            int appPid = getprocpid();
55e509ee18Sopenharmony_ci            std::string pidStr = std::to_string(appPid);
56e509ee18Sopenharmony_ci            std::string instanceIdStr("");
57e509ee18Sopenharmony_ci
58e509ee18Sopenharmony_ci            if (debugInfo_.instanceId != 0) {
59e509ee18Sopenharmony_ci                instanceIdStr = std::to_string(debugInfo_.instanceId);
60e509ee18Sopenharmony_ci            }
61e509ee18Sopenharmony_ci            std::string sockName = pidStr + instanceIdStr + debugInfo_.componentName;
62e509ee18Sopenharmony_ci            LOGI("WsServer RunServer fport localabstract: %{public}d%{public}s%{public}s",
63e509ee18Sopenharmony_ci                appPid, instanceIdStr.c_str(), debugInfo_.componentName.c_str());
64e509ee18Sopenharmony_ci            if (!webSocket_->InitUnixWebSocket(sockName)) {
65e509ee18Sopenharmony_ci                return;
66e509ee18Sopenharmony_ci            }
67e509ee18Sopenharmony_ci        } else {
68e509ee18Sopenharmony_ci            LOGI("WsServer RunServer fport ark: %{public}d", debugInfo_.socketfd);
69e509ee18Sopenharmony_ci            if (!webSocket_->InitUnixWebSocket(debugInfo_.socketfd)) {
70e509ee18Sopenharmony_ci                return;
71e509ee18Sopenharmony_ci            }
72e509ee18Sopenharmony_ci        }
73e509ee18Sopenharmony_ci#endif
74e509ee18Sopenharmony_ci    }
75e509ee18Sopenharmony_ci    ContinueRunserver();
76e509ee18Sopenharmony_ci}
77e509ee18Sopenharmony_civoid WsServer::ContinueRunserver()
78e509ee18Sopenharmony_ci{
79e509ee18Sopenharmony_ci    while (!terminateExecution_) {
80e509ee18Sopenharmony_ci#if !defined(OHOS_PLATFORM)
81e509ee18Sopenharmony_ci        if (!webSocket_->AcceptNewConnection()) {
82e509ee18Sopenharmony_ci            return;
83e509ee18Sopenharmony_ci        }
84e509ee18Sopenharmony_ci#else
85e509ee18Sopenharmony_ci        int runSeverInOldProcess = -2;
86e509ee18Sopenharmony_ci        if (debugInfo_.socketfd == runSeverInOldProcess) {
87e509ee18Sopenharmony_ci            if (!webSocket_->AcceptNewConnection()) {
88e509ee18Sopenharmony_ci                return;
89e509ee18Sopenharmony_ci            }
90e509ee18Sopenharmony_ci        } else {
91e509ee18Sopenharmony_ci            if (!webSocket_->ConnectUnixWebSocketBySocketpair()) {
92e509ee18Sopenharmony_ci                return;
93e509ee18Sopenharmony_ci            }
94e509ee18Sopenharmony_ci        }
95e509ee18Sopenharmony_ci#endif
96e509ee18Sopenharmony_ci        while (webSocket_->IsConnected()) {
97e509ee18Sopenharmony_ci            std::string message = webSocket_->Decode();
98e509ee18Sopenharmony_ci            if (!message.empty() && webSocket_->IsDecodeDisconnectMsg(message)) {
99e509ee18Sopenharmony_ci                LOGI("WsServer receiving disconnect msg: %{public}s", message.c_str());
100e509ee18Sopenharmony_ci                NotifyDisconnectEvent();
101e509ee18Sopenharmony_ci            } else if (!message.empty()) {
102e509ee18Sopenharmony_ci                LOGI("WsServer OnMessage: %{public}s", message.c_str());
103e509ee18Sopenharmony_ci                wsOnMessage_(std::move(message));
104e509ee18Sopenharmony_ci            }
105e509ee18Sopenharmony_ci        }
106e509ee18Sopenharmony_ci    }
107e509ee18Sopenharmony_ci}
108e509ee18Sopenharmony_ci
109e509ee18Sopenharmony_civoid WsServer::StopServer()
110e509ee18Sopenharmony_ci{
111e509ee18Sopenharmony_ci    LOGI("WsServer StopServer");
112e509ee18Sopenharmony_ci    {
113e509ee18Sopenharmony_ci        std::lock_guard<std::mutex> lock(wsMutex_);
114e509ee18Sopenharmony_ci        terminateExecution_ = true;
115e509ee18Sopenharmony_ci        if (webSocket_ != nullptr) {
116e509ee18Sopenharmony_ci            webSocket_->Close();
117e509ee18Sopenharmony_ci        }
118e509ee18Sopenharmony_ci    }
119e509ee18Sopenharmony_ci    pthread_join(tid_, nullptr);
120e509ee18Sopenharmony_ci    if (webSocket_ != nullptr) {
121e509ee18Sopenharmony_ci        webSocket_.reset();
122e509ee18Sopenharmony_ci    }
123e509ee18Sopenharmony_ci}
124e509ee18Sopenharmony_ci
125e509ee18Sopenharmony_civoid WsServer::SendReply(const std::string& message) const
126e509ee18Sopenharmony_ci{
127e509ee18Sopenharmony_ci    std::unique_lock<std::shared_mutex> lock(g_mutex);
128e509ee18Sopenharmony_ci    if (webSocket_ == nullptr) {
129e509ee18Sopenharmony_ci        LOGE("WsServer SendReply websocket has been closed unexpectedly");
130e509ee18Sopenharmony_ci        return;
131e509ee18Sopenharmony_ci    }
132e509ee18Sopenharmony_ci    LOGI("WsServer SendReply: %{public}s", message.c_str());
133e509ee18Sopenharmony_ci    if (!webSocket_->SendReply(message)) {
134e509ee18Sopenharmony_ci        LOGE("WsServer SendReply send fail");
135e509ee18Sopenharmony_ci        NotifyDisconnectEvent();
136e509ee18Sopenharmony_ci    }
137e509ee18Sopenharmony_ci}
138e509ee18Sopenharmony_ci
139e509ee18Sopenharmony_civoid WsServer::NotifyDisconnectEvent() const
140e509ee18Sopenharmony_ci{
141e509ee18Sopenharmony_ci    std::string message = "{\"id\":0, \"method\":\"Debugger.clientDisconnect\", \"params\":{}}";
142e509ee18Sopenharmony_ci    wsOnMessage_(std::move(message));
143e509ee18Sopenharmony_ci}
144e509ee18Sopenharmony_ci} // namespace OHOS::ArkCompiler::Toolchain
145