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