1/* 2 * Copyright (c) 2022 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 18#include <fstream> 19#include <iostream> 20#include <shared_mutex> 21#include <sys/types.h> 22#include <unistd.h> 23 24#include "common/log_wrapper.h" 25#include "websocket/server/websocket_server.h" 26 27namespace OHOS::ArkCompiler::Toolchain { 28std::shared_mutex g_mutex; 29 30// defined in .cpp file for WebSocketServer forward declaration 31WsServer::WsServer(const DebugInfo& debugInfo, const std::function<void(std::string&&)>& onMessage) 32 : debugInfo_(debugInfo), wsOnMessage_(onMessage) 33{} 34 35WsServer::~WsServer() = default; 36 37void WsServer::RunServer() 38{ 39 { 40 std::lock_guard<std::mutex> lock(wsMutex_); 41 if (terminateExecution_) { 42 LOGE("WsServer has been terminated unexpectedly"); 43 return; 44 } 45 webSocket_ = std::make_unique<WebSocketServer>(); 46#if !defined(OHOS_PLATFORM) 47 LOGI("WsSever Runsever: Init tcp websocket %{public}d", debugInfo_.port); 48 if (!webSocket_->InitTcpWebSocket(debugInfo_.port)) { 49 return; 50 } 51#else 52 int runSeverInOldProcess = -2; 53 if (debugInfo_.socketfd == runSeverInOldProcess) { 54 int appPid = getprocpid(); 55 std::string pidStr = std::to_string(appPid); 56 std::string instanceIdStr(""); 57 58 if (debugInfo_.instanceId != 0) { 59 instanceIdStr = std::to_string(debugInfo_.instanceId); 60 } 61 std::string sockName = pidStr + instanceIdStr + debugInfo_.componentName; 62 LOGI("WsServer RunServer fport localabstract: %{public}d%{public}s%{public}s", 63 appPid, instanceIdStr.c_str(), debugInfo_.componentName.c_str()); 64 if (!webSocket_->InitUnixWebSocket(sockName)) { 65 return; 66 } 67 } else { 68 LOGI("WsServer RunServer fport ark: %{public}d", debugInfo_.socketfd); 69 if (!webSocket_->InitUnixWebSocket(debugInfo_.socketfd)) { 70 return; 71 } 72 } 73#endif 74 } 75 ContinueRunserver(); 76} 77void 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 109void 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 125void 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 139void 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