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