• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "host/commands/cvd/server_client.h"
18 
19 #include <atomic>
20 #include <condition_variable>
21 #include <memory>
22 #include <optional>
23 #include <queue>
24 #include <thread>
25 
26 #include "cvd_server.pb.h"
27 
28 #include "common/libs/fs/shared_fd.h"
29 #include "common/libs/fs/shared_select.h"
30 #include "common/libs/utils/result.h"
31 #include "common/libs/utils/unix_sockets.h"
32 
33 namespace cuttlefish {
34 
GetClient(const SharedFD & client)35 Result<UnixMessageSocket> GetClient(const SharedFD& client) {
36   UnixMessageSocket result(client);
37   CF_EXPECT(result.EnableCredentials(true),
38             "Unable to enable UnixMessageSocket credentials.");
39   return result;
40 }
41 
GetRequest(const SharedFD & client)42 Result<std::optional<RequestWithStdio>> GetRequest(const SharedFD& client) {
43   UnixMessageSocket reader =
44       CF_EXPECT(GetClient(client), "Couldn't get client");
45   auto read_result = CF_EXPECT(reader.ReadMessage(), "Couldn't read message");
46 
47   if (read_result.data.empty()) {
48     LOG(VERBOSE) << "Read empty packet, so the client has probably closed the "
49                     "connection.";
50     return {};
51   };
52 
53   std::string serialized(read_result.data.begin(), read_result.data.end());
54   cvd::Request request;
55   CF_EXPECT(request.ParseFromString(serialized),
56             "Unable to parse serialized request proto.");
57 
58   CF_EXPECT(read_result.HasFileDescriptors(),
59             "Missing stdio fds from request.");
60   auto fds = CF_EXPECT(read_result.FileDescriptors(),
61                        "Error reading stdio fds from request");
62   CF_EXPECT(fds.size() == 3 || fds.size() == 4, "Wrong number of FDs, received "
63                                                     << fds.size()
64                                                     << ", wanted 3 or 4");
65 
66   std::optional<ucred> creds;
67   if (read_result.HasCredentials()) {
68     // TODO(b/198453477): Use Credentials to control command access.
69     creds = CF_EXPECT(read_result.Credentials(), "Failed to get credentials");
70     LOG(DEBUG) << "Has credentials, uid=" << creds->uid;
71   }
72 
73   return RequestWithStdio(client, std::move(request), std::move(fds),
74                           std::move(creds));
75 }
76 
SendResponse(const SharedFD & client,const cvd::Response & response)77 Result<void> SendResponse(const SharedFD& client,
78                           const cvd::Response& response) {
79   std::string serialized;
80   CF_EXPECT(response.SerializeToString(&serialized),
81             "Unable to serialize response proto.");
82   UnixSocketMessage message;
83   message.data = std::vector<char>(serialized.begin(), serialized.end());
84 
85   UnixMessageSocket writer =
86       CF_EXPECT(GetClient(client), "Couldn't get client");
87   CF_EXPECT(writer.WriteMessage(message));
88   return {};
89 }
90 
RequestWithStdio(SharedFD client_fd,cvd::Request message,std::vector<SharedFD> fds,std::optional<ucred> creds)91 RequestWithStdio::RequestWithStdio(SharedFD client_fd, cvd::Request message,
92                                    std::vector<SharedFD> fds,
93                                    std::optional<ucred> creds)
94     : client_fd_(client_fd),
95       message_(message),
96       fds_(std::move(fds)),
97       creds_(creds) {}
98 
Client() const99 SharedFD RequestWithStdio::Client() const { return client_fd_; }
100 
Message() const101 const cvd::Request& RequestWithStdio::Message() const { return message_; }
102 
FileDescriptors() const103 const std::vector<SharedFD>& RequestWithStdio::FileDescriptors() const {
104   return fds_;
105 }
106 
In() const107 SharedFD RequestWithStdio::In() const {
108   return fds_.size() > 0 ? fds_[0] : SharedFD();
109 }
110 
Out() const111 SharedFD RequestWithStdio::Out() const {
112   return fds_.size() > 1 ? fds_[1] : SharedFD();
113 }
114 
Err() const115 SharedFD RequestWithStdio::Err() const {
116   return fds_.size() > 2 ? fds_[2] : SharedFD();
117 }
118 
Extra() const119 std::optional<SharedFD> RequestWithStdio::Extra() const {
120   return fds_.size() > 3 ? fds_[3] : std::optional<SharedFD>{};
121 }
122 
Credentials() const123 std::optional<ucred> RequestWithStdio::Credentials() const { return creds_; }
124 
125 }  // namespace cuttlefish
126