• 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(std::move(request), std::move(fds), std::move(creds));
74 }
75 
SendResponse(const SharedFD & client,const cvd::Response & response)76 Result<void> SendResponse(const SharedFD& client,
77                           const cvd::Response& response) {
78   std::string serialized;
79   CF_EXPECT(response.SerializeToString(&serialized),
80             "Unable to serialize response proto.");
81   UnixSocketMessage message;
82   message.data = std::vector<char>(serialized.begin(), serialized.end());
83 
84   UnixMessageSocket writer =
85       CF_EXPECT(GetClient(client), "Couldn't get client");
86   CF_EXPECT(writer.WriteMessage(message));
87   return {};
88 }
89 
RequestWithStdio(cvd::Request message,std::vector<SharedFD> fds,std::optional<ucred> creds)90 RequestWithStdio::RequestWithStdio(cvd::Request message,
91                                    std::vector<SharedFD> fds,
92                                    std::optional<ucred> creds)
93     : message_(message), fds_(std::move(fds)), creds_(creds) {}
94 
Message() const95 const cvd::Request& RequestWithStdio::Message() const { return message_; }
96 
FileDescriptors() const97 const std::vector<SharedFD>& RequestWithStdio::FileDescriptors() const {
98   return fds_;
99 }
100 
In() const101 SharedFD RequestWithStdio::In() const {
102   return fds_.size() > 0 ? fds_[0] : SharedFD();
103 }
104 
Out() const105 SharedFD RequestWithStdio::Out() const {
106   return fds_.size() > 1 ? fds_[1] : SharedFD();
107 }
108 
Err() const109 SharedFD RequestWithStdio::Err() const {
110   return fds_.size() > 2 ? fds_[2] : SharedFD();
111 }
112 
Extra() const113 std::optional<SharedFD> RequestWithStdio::Extra() const {
114   return fds_.size() > 3 ? fds_[3] : std::optional<SharedFD>{};
115 }
116 
Credentials() const117 std::optional<ucred> RequestWithStdio::Credentials() const { return creds_; }
118 
119 }  // namespace cuttlefish
120