1 // Copyright (C) 2020 The Android Open Source Project 2 // 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 #pragma once 16 17 #include <poll.h> 18 19 #include <cstdio> 20 #include <cstring> 21 #include <functional> 22 #include <future> 23 #include <iostream> 24 #include <mutex> 25 #include <sstream> 26 #include <string> 27 #include <thread> 28 #include <vector> 29 30 #include <android-base/unique_fd.h> 31 #include "snapuserd.h" 32 33 namespace android { 34 namespace snapshot { 35 36 static constexpr uint32_t MAX_PACKET_SIZE = 512; 37 38 enum class DaemonOperations { 39 INIT, 40 START, 41 QUERY, 42 STOP, 43 DELETE, 44 DETACH, 45 SUPPORTS, 46 INVALID, 47 }; 48 49 class DmUserHandler { 50 public: 51 explicit DmUserHandler(std::shared_ptr<Snapuserd> snapuserd); 52 FreeResources()53 void FreeResources() { 54 // Each worker thread holds a reference to snapuserd. 55 // Clear them so that all the resources 56 // held by snapuserd is released 57 if (snapuserd_) { 58 snapuserd_->FreeResources(); 59 snapuserd_ = nullptr; 60 } 61 } snapuserd()62 const std::shared_ptr<Snapuserd>& snapuserd() const { return snapuserd_; } thread()63 std::thread& thread() { return thread_; } 64 misc_name()65 const std::string& misc_name() const { return misc_name_; } 66 67 private: 68 std::thread thread_; 69 std::shared_ptr<Snapuserd> snapuserd_; 70 std::string misc_name_; 71 }; 72 73 class Stoppable { 74 std::promise<void> exitSignal_; 75 std::future<void> futureObj_; 76 77 public: Stoppable()78 Stoppable() : futureObj_(exitSignal_.get_future()) {} 79 ~Stoppable()80 virtual ~Stoppable() {} 81 StopRequested()82 bool StopRequested() { 83 // checks if value in future object is available 84 if (futureObj_.wait_for(std::chrono::milliseconds(0)) == std::future_status::timeout) { 85 return false; 86 } 87 return true; 88 } 89 // Request the thread to stop by setting value in promise object StopThreads()90 void StopThreads() { exitSignal_.set_value(); } 91 }; 92 93 class SnapuserdServer : public Stoppable { 94 private: 95 android::base::unique_fd sockfd_; 96 bool terminating_; 97 volatile bool received_socket_signal_ = false; 98 std::vector<struct pollfd> watched_fds_; 99 bool is_socket_present_ = false; 100 101 std::mutex lock_; 102 103 using HandlerList = std::vector<std::shared_ptr<DmUserHandler>>; 104 HandlerList dm_users_; 105 106 void AddWatchedFd(android::base::borrowed_fd fd, int events); 107 void AcceptClient(); 108 bool HandleClient(android::base::borrowed_fd fd, int revents); 109 bool Recv(android::base::borrowed_fd fd, std::string* data); 110 bool Sendmsg(android::base::borrowed_fd fd, const std::string& msg); 111 bool Receivemsg(android::base::borrowed_fd fd, const std::string& str); 112 113 void ShutdownThreads(); 114 bool RemoveAndJoinHandler(const std::string& control_device); 115 DaemonOperations Resolveop(std::string& input); 116 std::string GetDaemonStatus(); 117 void Parsemsg(std::string const& msg, const char delim, std::vector<std::string>& out); 118 IsTerminating()119 bool IsTerminating() { return terminating_; } 120 121 void RunThread(std::shared_ptr<DmUserHandler> handler); 122 void JoinAllThreads(); 123 bool StartWithSocket(bool start_listening); 124 125 // Find a DmUserHandler within a lock. 126 HandlerList::iterator FindHandler(std::lock_guard<std::mutex>* proof_of_lock, 127 const std::string& misc_name); 128 129 public: SnapuserdServer()130 SnapuserdServer() { terminating_ = false; } 131 ~SnapuserdServer(); 132 133 bool Start(const std::string& socketname); 134 bool Run(); 135 void Interrupt(); 136 bool RunForSocketHandoff(); 137 bool WaitForSocket(); 138 139 std::shared_ptr<DmUserHandler> AddHandler(const std::string& misc_name, 140 const std::string& cow_device_path, 141 const std::string& backing_device); 142 bool StartHandler(const std::shared_ptr<DmUserHandler>& handler); 143 SetTerminating()144 void SetTerminating() { terminating_ = true; } ReceivedSocketSignal()145 void ReceivedSocketSignal() { received_socket_signal_ = true; } 146 }; 147 148 } // namespace snapshot 149 } // namespace android 150