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