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 INVALID, 46 }; 47 48 class DmUserHandler { 49 public: 50 explicit DmUserHandler(std::shared_ptr<Snapuserd> snapuserd); 51 FreeResources()52 void FreeResources() { 53 // Each worker thread holds a reference to snapuserd. 54 // Clear them so that all the resources 55 // held by snapuserd is released 56 if (snapuserd_) { 57 snapuserd_->FreeResources(); 58 snapuserd_ = nullptr; 59 } 60 } snapuserd()61 const std::shared_ptr<Snapuserd>& snapuserd() const { return snapuserd_; } thread()62 std::thread& thread() { return thread_; } 63 misc_name()64 const std::string& misc_name() const { return misc_name_; } 65 66 private: 67 std::thread thread_; 68 std::shared_ptr<Snapuserd> snapuserd_; 69 std::string misc_name_; 70 }; 71 72 class Stoppable { 73 std::promise<void> exitSignal_; 74 std::future<void> futureObj_; 75 76 public: Stoppable()77 Stoppable() : futureObj_(exitSignal_.get_future()) {} 78 ~Stoppable()79 virtual ~Stoppable() {} 80 StopRequested()81 bool StopRequested() { 82 // checks if value in future object is available 83 if (futureObj_.wait_for(std::chrono::milliseconds(0)) == std::future_status::timeout) { 84 return false; 85 } 86 return true; 87 } 88 // Request the thread to stop by setting value in promise object StopThreads()89 void StopThreads() { exitSignal_.set_value(); } 90 }; 91 92 class SnapuserdServer : public Stoppable { 93 private: 94 android::base::unique_fd sockfd_; 95 bool terminating_; 96 std::vector<struct pollfd> watched_fds_; 97 98 std::mutex lock_; 99 100 using HandlerList = std::vector<std::shared_ptr<DmUserHandler>>; 101 HandlerList dm_users_; 102 103 void AddWatchedFd(android::base::borrowed_fd fd); 104 void AcceptClient(); 105 bool HandleClient(android::base::borrowed_fd fd, int revents); 106 bool Recv(android::base::borrowed_fd fd, std::string* data); 107 bool Sendmsg(android::base::borrowed_fd fd, const std::string& msg); 108 bool Receivemsg(android::base::borrowed_fd fd, const std::string& str); 109 110 void ShutdownThreads(); 111 bool RemoveAndJoinHandler(const std::string& control_device); 112 DaemonOperations Resolveop(std::string& input); 113 std::string GetDaemonStatus(); 114 void Parsemsg(std::string const& msg, const char delim, std::vector<std::string>& out); 115 IsTerminating()116 bool IsTerminating() { return terminating_; } 117 118 void RunThread(std::shared_ptr<DmUserHandler> handler); 119 void JoinAllThreads(); 120 121 // Find a DmUserHandler within a lock. 122 HandlerList::iterator FindHandler(std::lock_guard<std::mutex>* proof_of_lock, 123 const std::string& misc_name); 124 125 public: SnapuserdServer()126 SnapuserdServer() { terminating_ = false; } 127 ~SnapuserdServer(); 128 129 bool Start(const std::string& socketname); 130 bool Run(); 131 void Interrupt(); 132 133 std::shared_ptr<DmUserHandler> AddHandler(const std::string& misc_name, 134 const std::string& cow_device_path, 135 const std::string& backing_device); 136 bool StartHandler(const std::shared_ptr<DmUserHandler>& handler); 137 SetTerminating()138 void SetTerminating() { terminating_ = true; } 139 }; 140 141 } // namespace snapshot 142 } // namespace android 143