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