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