12498b56bSopenharmony_ci/*
22498b56bSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
32498b56bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
42498b56bSopenharmony_ci * you may not use this file except in compliance with the License.
52498b56bSopenharmony_ci * You may obtain a copy of the License at
62498b56bSopenharmony_ci *
72498b56bSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
82498b56bSopenharmony_ci *
92498b56bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
102498b56bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
112498b56bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
122498b56bSopenharmony_ci * See the License for the specific language governing permissions and
132498b56bSopenharmony_ci * limitations under the License.
142498b56bSopenharmony_ci */
152498b56bSopenharmony_ci#include <algorithm>
162498b56bSopenharmony_ci#include <cstring>
172498b56bSopenharmony_ci#include <iostream>
182498b56bSopenharmony_ci#include <memory>
192498b56bSopenharmony_ci#include <mutex>
202498b56bSopenharmony_ci#include <thread>
212498b56bSopenharmony_ci#include <sys/prctl.h>
222498b56bSopenharmony_ci#include <sys/stat.h>
232498b56bSopenharmony_ci#include <unistd.h>
242498b56bSopenharmony_ci
252498b56bSopenharmony_ci#include <log_utils.h>
262498b56bSopenharmony_ci#include <seq_packet_socket_server.h>
272498b56bSopenharmony_ci
282498b56bSopenharmony_ci#include "service_controller.h"
292498b56bSopenharmony_ci#include "cmd_executor.h"
302498b56bSopenharmony_ci
312498b56bSopenharmony_cinamespace OHOS {
322498b56bSopenharmony_cinamespace HiviewDFX {
332498b56bSopenharmony_cistatic const int MAX_CLIENT_CONNECTIONS = 100;
342498b56bSopenharmony_ci
352498b56bSopenharmony_ciCmdExecutor::~CmdExecutor()
362498b56bSopenharmony_ci{
372498b56bSopenharmony_ci    std::lock_guard<std::mutex> lg(m_clientAccess);
382498b56bSopenharmony_ci    for (auto& client : m_clients) {
392498b56bSopenharmony_ci        client->m_stopThread.store(true);
402498b56bSopenharmony_ci    }
412498b56bSopenharmony_ci    for (auto& client : m_clients) {
422498b56bSopenharmony_ci        if (client->m_clientThread.joinable()) {
432498b56bSopenharmony_ci            client->m_clientThread.join();
442498b56bSopenharmony_ci        }
452498b56bSopenharmony_ci    }
462498b56bSopenharmony_ci}
472498b56bSopenharmony_ci
482498b56bSopenharmony_civoid CmdExecutor::MainLoop(const std::string& socketName)
492498b56bSopenharmony_ci{
502498b56bSopenharmony_ci    SeqPacketSocketServer cmdServer(socketName, MAX_CLIENT_CONNECTIONS);
512498b56bSopenharmony_ci    if (cmdServer.Init() < 0) {
522498b56bSopenharmony_ci        std::cerr << "Failed to init control socket ! \n";
532498b56bSopenharmony_ci        return;
542498b56bSopenharmony_ci    }
552498b56bSopenharmony_ci    std::cout << "Server started to listen !\n";
562498b56bSopenharmony_ci    using namespace std::chrono_literals;
572498b56bSopenharmony_ci    cmdServer.StartAcceptingConnection(
582498b56bSopenharmony_ci        [this] (std::unique_ptr<Socket> handler) {
592498b56bSopenharmony_ci            OnAcceptedConnection(std::move(handler));
602498b56bSopenharmony_ci        },
612498b56bSopenharmony_ci        3000ms,
622498b56bSopenharmony_ci        [this] () {
632498b56bSopenharmony_ci            CleanFinishedClients();
642498b56bSopenharmony_ci        });
652498b56bSopenharmony_ci}
662498b56bSopenharmony_ci
672498b56bSopenharmony_civoid CmdExecutor::OnAcceptedConnection(std::unique_ptr<Socket> handler)
682498b56bSopenharmony_ci{
692498b56bSopenharmony_ci    std::lock_guard<std::mutex> lg(m_clientAccess);
702498b56bSopenharmony_ci    auto newVal = std::make_unique<ClientThread>();
712498b56bSopenharmony_ci    if (newVal != nullptr) {
722498b56bSopenharmony_ci        newVal->m_stopThread.store(false);
732498b56bSopenharmony_ci        newVal->m_clientThread = std::thread([this](std::unique_ptr<Socket> handler) {
742498b56bSopenharmony_ci            ClientEventLoop(std::move(handler));
752498b56bSopenharmony_ci        }, std::move(handler));
762498b56bSopenharmony_ci        m_clients.push_back(std::move(newVal));
772498b56bSopenharmony_ci    }
782498b56bSopenharmony_ci}
792498b56bSopenharmony_ci
802498b56bSopenharmony_civoid CmdExecutor::ClientEventLoop(std::unique_ptr<Socket> handler)
812498b56bSopenharmony_ci{
822498b56bSopenharmony_ci    decltype(m_clients)::iterator clientInfoIt;
832498b56bSopenharmony_ci    {
842498b56bSopenharmony_ci        std::lock_guard<std::mutex> lg(m_clientAccess);
852498b56bSopenharmony_ci        clientInfoIt = std::find_if(m_clients.begin(), m_clients.end(),
862498b56bSopenharmony_ci            [](const std::unique_ptr<ClientThread>& ct) {
872498b56bSopenharmony_ci                return ct->m_clientThread.get_id() == std::this_thread::get_id();
882498b56bSopenharmony_ci            });
892498b56bSopenharmony_ci    }
902498b56bSopenharmony_ci    if (clientInfoIt == m_clients.end()) {
912498b56bSopenharmony_ci        std::cerr << "Failed to find client\n";
922498b56bSopenharmony_ci        return;
932498b56bSopenharmony_ci    }
942498b56bSopenharmony_ci
952498b56bSopenharmony_ci    prctl(PR_SET_NAME, m_name.c_str());
962498b56bSopenharmony_ci    ServiceController serviceCtrl(std::move(handler), m_logCollector, m_hilogBuffer, m_kmsgBuffer);
972498b56bSopenharmony_ci    serviceCtrl.CommunicationLoop((*clientInfoIt)->m_stopThread, m_cmdList);
982498b56bSopenharmony_ci
992498b56bSopenharmony_ci    std::lock_guard<std::mutex> ul(m_finishedClientAccess);
1002498b56bSopenharmony_ci    m_finishedClients.push_back(std::this_thread::get_id());
1012498b56bSopenharmony_ci}
1022498b56bSopenharmony_ci
1032498b56bSopenharmony_civoid CmdExecutor::CleanFinishedClients()
1042498b56bSopenharmony_ci{
1052498b56bSopenharmony_ci    std::list<std::thread> threadsToJoin;
1062498b56bSopenharmony_ci    {
1072498b56bSopenharmony_ci        // select clients to clean up - pick threads that we have to be sure are ended
1082498b56bSopenharmony_ci        std::scoped_lock sl(m_finishedClientAccess, m_clientAccess);
1092498b56bSopenharmony_ci        for (auto threadId : m_finishedClients) {
1102498b56bSopenharmony_ci            auto clientInfoIt = std::find_if(m_clients.begin(), m_clients.end(),
1112498b56bSopenharmony_ci                [&threadId](const std::unique_ptr<ClientThread>& ct) {
1122498b56bSopenharmony_ci                    return ct->m_clientThread.get_id() == threadId;
1132498b56bSopenharmony_ci                });
1142498b56bSopenharmony_ci            if (clientInfoIt != m_clients.end()) {
1152498b56bSopenharmony_ci                threadsToJoin.push_back(std::move((*clientInfoIt)->m_clientThread));
1162498b56bSopenharmony_ci                m_clients.erase(clientInfoIt);
1172498b56bSopenharmony_ci            }
1182498b56bSopenharmony_ci        }
1192498b56bSopenharmony_ci        m_finishedClients.clear();
1202498b56bSopenharmony_ci    }
1212498b56bSopenharmony_ci    for (auto& thread : threadsToJoin) {
1222498b56bSopenharmony_ci        if (thread.joinable()) {
1232498b56bSopenharmony_ci            thread.join();
1242498b56bSopenharmony_ci        }
1252498b56bSopenharmony_ci    }
1262498b56bSopenharmony_ci}
1272498b56bSopenharmony_ci} // namespace HiviewDFX
1282498b56bSopenharmony_ci} // namespace OHOS
129