1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 #include <atomic> 20 #include <map> 21 #include <optional> 22 #include <shared_mutex> 23 #include <string> 24 #include <vector> 25 26 #include <fruit/fruit.h> 27 28 #include "cvd_server.pb.h" 29 30 #include "common/libs/fs/epoll.h" 31 #include "common/libs/fs/shared_fd.h" 32 #include "common/libs/utils/result.h" 33 #include "common/libs/utils/subprocess.h" 34 #include "common/libs/utils/unix_sockets.h" 35 #include "host/commands/cvd/epoll_loop.h" 36 #include "host/commands/cvd/instance_manager.h" 37 #include "host/commands/cvd/server_client.h" 38 39 namespace cuttlefish { 40 41 class CvdServerHandler { 42 public: 43 virtual ~CvdServerHandler() = default; 44 45 virtual Result<bool> CanHandle(const RequestWithStdio&) const = 0; 46 virtual Result<cvd::Response> Handle(const RequestWithStdio&) = 0; 47 virtual Result<void> Interrupt() = 0; 48 }; 49 50 class CvdServer { 51 public: 52 INJECT(CvdServer(EpollPool&, InstanceManager&)); 53 ~CvdServer(); 54 55 Result<void> StartServer(SharedFD server); 56 void Stop(); 57 void Join(); 58 59 private: 60 struct OngoingRequest { 61 CvdServerHandler* handler; 62 std::mutex mutex; 63 std::thread::id thread_id; 64 }; 65 66 Result<void> AcceptClient(EpollEvent); 67 Result<void> HandleMessage(EpollEvent); 68 Result<cvd::Response> HandleRequest(RequestWithStdio, SharedFD client); 69 Result<void> BestEffortWakeup(); 70 71 EpollPool& epoll_pool_; 72 InstanceManager& instance_manager_; 73 std::atomic_bool running_ = true; 74 75 std::mutex ongoing_requests_mutex_; 76 std::set<std::shared_ptr<OngoingRequest>> ongoing_requests_; 77 // TODO(schuffelen): Move this thread pool to another class. 78 std::mutex threads_mutex_; 79 std::vector<std::thread> threads_; 80 }; 81 82 class CvdCommandHandler : public CvdServerHandler { 83 public: 84 INJECT(CvdCommandHandler(InstanceManager& instance_manager)); 85 86 Result<bool> CanHandle(const RequestWithStdio&) const override; 87 Result<cvd::Response> Handle(const RequestWithStdio&) override; 88 Result<void> Interrupt() override; 89 90 private: 91 InstanceManager& instance_manager_; 92 std::optional<Subprocess> subprocess_; 93 std::mutex interruptible_; 94 bool interrupted_ = false; 95 }; 96 97 fruit::Component<fruit::Required<InstanceManager>> cvdCommandComponent(); 98 fruit::Component<fruit::Required<CvdServer, InstanceManager>> 99 cvdShutdownComponent(); 100 fruit::Component<> cvdVersionComponent(); 101 fruit::Component<fruit::Required<CvdCommandHandler>> AcloudCommandComponent(); 102 103 struct CommandInvocation { 104 std::string command; 105 std::vector<std::string> arguments; 106 }; 107 108 CommandInvocation ParseInvocation(const cvd::Request& request); 109 110 Result<int> CvdServerMain(SharedFD server_fd); 111 112 } // namespace cuttlefish 113