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 "connect_server.h"
17e509ee18Sopenharmony_ci#include <mutex>
18e509ee18Sopenharmony_ci#include <shared_mutex>
19e509ee18Sopenharmony_ci#include <unistd.h>
20e509ee18Sopenharmony_ci#include "common/log_wrapper.h"
21e509ee18Sopenharmony_ci#include "websocket/server/websocket_server.h"
22e509ee18Sopenharmony_ci
23e509ee18Sopenharmony_cinamespace OHOS::ArkCompiler::Toolchain {
24e509ee18Sopenharmony_cistd::shared_mutex g_sendMutex;
25e509ee18Sopenharmony_ci
26e509ee18Sopenharmony_ci// defined in .cpp file for WebSocketServer forward declaration
27e509ee18Sopenharmony_ciConnectServer::ConnectServer(int socketfd, std::function<void(std::string&&)> onMessage)
28e509ee18Sopenharmony_ci    : socketfd_(socketfd), wsOnMessage_(std::move(onMessage))
29e509ee18Sopenharmony_ci{}
30e509ee18Sopenharmony_ci
31e509ee18Sopenharmony_ciConnectServer::ConnectServer(const std::string& bundleName, std::function<void(std::string&&)> onMessage)
32e509ee18Sopenharmony_ci    : bundleName_(bundleName), wsOnMessage_(std::move(onMessage))
33e509ee18Sopenharmony_ci{}
34e509ee18Sopenharmony_ci
35e509ee18Sopenharmony_ciConnectServer::~ConnectServer() = default;
36e509ee18Sopenharmony_ci
37e509ee18Sopenharmony_civoid ConnectServer::RunServer()
38e509ee18Sopenharmony_ci{
39e509ee18Sopenharmony_ci    terminateExecution_ = false;
40e509ee18Sopenharmony_ci    webSocket_ = std::make_unique<WebSocketServer>();
41e509ee18Sopenharmony_ci    tid_ = pthread_self();
42e509ee18Sopenharmony_ci#if defined(OHOS_PLATFORM)
43e509ee18Sopenharmony_ci    int runSeverInOldProcess = -2; // run sever in old process.
44e509ee18Sopenharmony_ci    int appPid = getprocpid();
45e509ee18Sopenharmony_ci    std::string pidStr = std::to_string(appPid);
46e509ee18Sopenharmony_ci    std::string sockName = pidStr + bundleName_;
47e509ee18Sopenharmony_ci    if (socketfd_ == runSeverInOldProcess) {
48e509ee18Sopenharmony_ci        if (!webSocket_->InitUnixWebSocket(sockName)) {
49e509ee18Sopenharmony_ci            return;
50e509ee18Sopenharmony_ci        }
51e509ee18Sopenharmony_ci    } else {
52e509ee18Sopenharmony_ci        if (!webSocket_->InitUnixWebSocket(socketfd_)) {
53e509ee18Sopenharmony_ci            return;
54e509ee18Sopenharmony_ci        }
55e509ee18Sopenharmony_ci    }
56e509ee18Sopenharmony_ci#endif
57e509ee18Sopenharmony_ci    while (!terminateExecution_) {
58e509ee18Sopenharmony_ci#if defined(OHOS_PLATFORM)
59e509ee18Sopenharmony_ci        if (socketfd_ == runSeverInOldProcess) {
60e509ee18Sopenharmony_ci            if (!webSocket_->AcceptNewConnection()) {
61e509ee18Sopenharmony_ci                return;
62e509ee18Sopenharmony_ci            }
63e509ee18Sopenharmony_ci        } else {
64e509ee18Sopenharmony_ci            if (!webSocket_->ConnectUnixWebSocketBySocketpair()) {
65e509ee18Sopenharmony_ci                return;
66e509ee18Sopenharmony_ci            }
67e509ee18Sopenharmony_ci        }
68e509ee18Sopenharmony_ci#endif
69e509ee18Sopenharmony_ci        while (webSocket_->IsConnected()) {
70e509ee18Sopenharmony_ci            std::string message = webSocket_->Decode();
71e509ee18Sopenharmony_ci            if (!message.empty()) {
72e509ee18Sopenharmony_ci                wsOnMessage_(std::move(message));
73e509ee18Sopenharmony_ci            }
74e509ee18Sopenharmony_ci        }
75e509ee18Sopenharmony_ci    }
76e509ee18Sopenharmony_ci}
77e509ee18Sopenharmony_ci
78e509ee18Sopenharmony_civoid ConnectServer::StopServer()
79e509ee18Sopenharmony_ci{
80e509ee18Sopenharmony_ci    LOGI("ConnectServer StopServer");
81e509ee18Sopenharmony_ci    terminateExecution_ = true;
82e509ee18Sopenharmony_ci    if (webSocket_ != nullptr) {
83e509ee18Sopenharmony_ci        webSocket_->Close();
84e509ee18Sopenharmony_ci        pthread_join(tid_, nullptr);
85e509ee18Sopenharmony_ci        webSocket_.reset();
86e509ee18Sopenharmony_ci    }
87e509ee18Sopenharmony_ci}
88e509ee18Sopenharmony_ci
89e509ee18Sopenharmony_civoid ConnectServer::SendMessage(const std::string& message) const
90e509ee18Sopenharmony_ci{
91e509ee18Sopenharmony_ci    std::unique_lock<std::shared_mutex> lock(g_sendMutex);
92e509ee18Sopenharmony_ci    if (webSocket_ == nullptr) {
93e509ee18Sopenharmony_ci        LOGE("ConnectServer SendReply websocket has been closed unexpectedly");
94e509ee18Sopenharmony_ci        return;
95e509ee18Sopenharmony_ci    }
96e509ee18Sopenharmony_ci    LOGI("ConnectServer SendReply: %{public}s", message.c_str());
97e509ee18Sopenharmony_ci    webSocket_->SendReply(message);
98e509ee18Sopenharmony_ci}
99e509ee18Sopenharmony_ci} // namespace OHOS::ArkCompiler::Toolchain
100