blob: 98a83f67aa93850330e5fbe6793b61be262ec3eb [file] [log] [blame]
Cody Schuffelen134ff032019-11-22 00:25:32 -08001/*
2 * Copyright (C) 2017 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#include "host/commands/ivserver/hald_client.h"
17
18#include <string>
19
20#include <glog/logging.h>
21
22namespace ivserver {
23namespace {
24// The protocol between host-clients and the ivserver could change.
25// Clients should verify what version they are talking to during the handshake.
26const uint32_t kHaldClientProtocolVersion = 0;
27} // anonymous namespace
28
29std::unique_ptr<HaldClient> HaldClient::New(const VSoCSharedMemory& shmem,
30 const cvd::SharedFD& clientfd) {
31 std::unique_ptr<HaldClient> res;
32
33 if (!clientfd->IsOpen()) {
34 LOG(WARNING) << "Invalid socket passed to HaldClient: "
35 << clientfd->StrError();
36 return res;
37 }
38
39 res.reset(new HaldClient(clientfd));
40 if (!res->PerformHandshake(shmem)) {
41 LOG(ERROR) << "HalD handshake failed. Dropping connection.";
42 res.reset();
43 }
44
45 return res;
46}
47
48HaldClient::HaldClient(const cvd::SharedFD& client_socket)
49 : client_socket_(client_socket) {}
50
51bool HaldClient::PerformHandshake(const VSoCSharedMemory& shared_mem) {
52 int rval =
53 client_socket_->Send(&kHaldClientProtocolVersion,
54 sizeof(kHaldClientProtocolVersion), MSG_NOSIGNAL);
55 if (rval != sizeof(kHaldClientProtocolVersion)) {
56 LOG(ERROR) << "failed to send protocol version: "
57 << client_socket_->StrError();
58 return false;
59 }
60
61 int16_t region_name_len;
62 if (client_socket_->Recv(&region_name_len, sizeof(region_name_len),
63 MSG_NOSIGNAL) != sizeof(region_name_len)) {
64 LOG(ERROR) << "Error receiving region name length: "
65 << client_socket_->StrError();
66 return false;
67 }
68
69 if (region_name_len <= 0 ||
70 region_name_len > VSOC_DEVICE_NAME_SZ) {
71 LOG(ERROR) << "Invalid region length received: " << region_name_len;
72 return false;
73 }
74
75 std::vector<char> region_name_data(region_name_len);
76 rval = client_socket_->Recv(region_name_data.data(), region_name_len,
77 MSG_NOSIGNAL);
78 if (rval != region_name_len) {
79 LOG(ERROR) << "Incomplete region name length received. Want: "
80 << region_name_len << ", got: " << rval;
81 return false;
82 }
83
84 std::string region_name(region_name_data.begin(), region_name_data.end());
85 LOG(INFO) << "New HALD requesting region: " << region_name;
86
87 // Send Host, Guest and SharedMemory FDs associated with this region.
88 cvd::SharedFD guest_to_host_efd;
89 cvd::SharedFD host_to_guest_efd;
90
91 if (!shared_mem.GetEventFdPairForRegion(region_name, &guest_to_host_efd,
92 &host_to_guest_efd)) {
93 LOG(ERROR) << "Region " << region_name << " was not found.";
94 return false;
95 }
96
97 if (!guest_to_host_efd->IsOpen()) {
98 LOG(ERROR) << "Host channel is not open; last known error: "
99 << guest_to_host_efd->StrError();
100 return false;
101 }
102
103 if (!host_to_guest_efd->IsOpen()) {
104 LOG(ERROR) << "Guest channel is not open; last known error: "
105 << host_to_guest_efd->StrError();
106 return false;
107 }
108
109 // TODO(ender): delete this once no longer necessary. Currently, absence of
110 // payload makes RecvMsgAndFDs hang forever.
111 uint64_t control_data = 0;
112 struct iovec vec {
113 &control_data, sizeof(control_data)
114 };
115 cvd::InbandMessageHeader hdr{nullptr, 0, &vec, 1, 0};
116 cvd::SharedFD fds[3] = {guest_to_host_efd, host_to_guest_efd,
117 shared_mem.SharedMemFD()};
118 rval = client_socket_->SendMsgAndFDs<3>(hdr, MSG_NOSIGNAL, fds);
119 if (rval == -1) {
120 LOG(ERROR) << "failed to send Host FD: " << client_socket_->StrError();
121 return false;
122 }
123
124 LOG(INFO) << "HALD managing region: " << region_name << " connected.";
125 return true;
126}
127
128} // namespace ivserver